- name: 2d.canvas.host.reference desc: canvas refers back to its canvas code: | @assert ctx.canvas === canvas; t.done(); - name: 2d.canvas.host.readonly desc: canvas is readonly code: | var offscreenCanvas2 = new OffscreenCanvas(100, 50); var d = ctx.canvas; @assert offscreenCanvas2 !== d; ctx.canvas = offscreenCanvas2; @assert ctx.canvas === d; t.done(); - name: 2d.canvas.context.exists desc: The 2D context is implemented code: | var offscreenCanvas2 = new OffscreenCanvas(100, 50); @assert offscreenCanvas2.getContext('2d') !== null; t.done(); - name: 2d.canvas.context.extraargs.create desc: The 2D context doesn't throw with extra getContext arguments (new context) code: | @assert (new OffscreenCanvas(100, 50)).getContext('2d', false, {}, [], 1, "2") !== null; @assert (new OffscreenCanvas(100, 50)).getContext('2d', 123) !== null; @assert (new OffscreenCanvas(100, 50)).getContext('2d', "test") !== null; @assert (new OffscreenCanvas(100, 50)).getContext('2d', undefined) !== null; @assert (new OffscreenCanvas(100, 50)).getContext('2d', null) !== null; @assert (new OffscreenCanvas(100, 50)).getContext('2d', Symbol.hasInstance) !== null; t.done(); - name: 2d.canvas.context.extraargs.cache desc: The 2D context doesn't throw with extra getContext arguments (cached) code: | @assert canvas.getContext('2d', false, {}, [], 1, "2") !== null; @assert canvas.getContext('2d', 123) !== null; @assert canvas.getContext('2d', "test") !== null; @assert canvas.getContext('2d', undefined) !== null; @assert canvas.getContext('2d', null) !== null; @assert canvas.getContext('2d', Symbol.hasInstance) !== null; t.done(); - name: 2d.canvas.context.unique desc: getContext('2d') returns the same object code: | var offscreenCanvas2 = new OffscreenCanvas(100, 50); @assert offscreenCanvas2.getContext('2d') === offscreenCanvas2.getContext('2d'); t.done(); - name: 2d.canvas.context.shared desc: getContext('2d') returns objects which share canvas state 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; t.done(); - name: 2d.canvas.context.emptystring desc: getContext with empty string returns null code: | var offscreenCanvas2 = new OffscreenCanvas(100, 50); @assert throws TypeError offscreenCanvas2.getContext(""); t.done(); - name: 2d.canvas.context.unrecognised.badname desc: getContext with unrecognised context name returns null code: | var offscreenCanvas2 = new OffscreenCanvas(100, 50); @assert throws TypeError offscreenCanvas2.getContext('This is not an implemented context in any real browser'); t.done(); - name: 2d.canvas.context.unrecognised.badsuffix desc: Context name "2d" plus a suffix is unrecognised code: | var offscreenCanvas2 = new OffscreenCanvas(100, 50); @assert throws TypeError offscreenCanvas2.getContext("2d#"); t.done(); - name: 2d.canvas.context.unrecognised.nullsuffix desc: Context name "2d" plus a "\0" suffix is unrecognised code: | var offscreenCanvas2 = new OffscreenCanvas(100, 50); @assert throws TypeError offscreenCanvas2.getContext("2d\0"); t.done(); - name: 2d.canvas.context.unrecognised.unicode desc: Context name which kind of looks like "2d" is unrecognised code: | var offscreenCanvas2 = new OffscreenCanvas(100, 50); @assert throws TypeError offscreenCanvas2.getContext("2\uFF44"); t.done(); - name: 2d.canvas.context.casesensitive desc: Context name "2D" is unrecognised; matching is case sensitive code: | var offscreenCanvas2 = new OffscreenCanvas(100, 50); @assert throws TypeError offscreenCanvas2.getContext('2D'); t.done(); - name: 2d.canvas.context.arguments.missing code: | var offscreenCanvas2 = new OffscreenCanvas(100, 50); @assert throws TypeError offscreenCanvas2.getContext(); @moz-todo t.done(); - name: 2d.canvas.host.initial.color desc: Initial state is transparent black code: | @assert pixel 20,20 == 0,0,0,0; t.done(); - name: 2d.canvas.host.initial.reset.different desc: Changing size resets canvas to transparent black 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; t.done(); - name: 2d.canvas.host.initial.reset.same desc: Setting size (not changing the value) resets canvas to transparent black 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; t.done(); - name: 2d.canvas.host.initial.reset.path desc: Resetting the canvas state resets the current path 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; t.done(); - name: 2d.canvas.host.initial.reset.clip desc: Resetting the canvas state resets the current clip region 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; t.done(); - name: 2d.canvas.host.initial.reset.transform desc: Resetting the canvas state resets the current transformation matrix 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; t.done(); - name: 2d.canvas.host.initial.reset.gradient desc: Resetting the canvas state does not invalidate any existing gradients 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; t.done(); - name: 2d.canvas.host.initial.reset.pattern desc: Resetting the canvas state does not invalidate any existing patterns 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; t.done(); - name: 2d.canvas.host.size.attributes.idl.set.zero desc: Setting width/height IDL attributes to 0 code: | canvas.width = 0; canvas.height = 0; @assert canvas.width === 0; @assert canvas.height === 0; t.done(); - name: 2d.canvas.host.size.attributes.idl desc: Getting/setting width/height IDL attributes 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 = 301.999; canvas.height = 301.001; @assert canvas.width === 301; @assert canvas.height === 301; @assert throws TypeError canvas.width = "400x"; @assert throws TypeError canvas.height = "foo"; @assert canvas.width === 301; @assert canvas.height === 301; t.done(); - name: 2d.canvas.host.size.attributes.default desc: Default width/height when attributes are missing code: | @assert canvas.width === 100; @assert canvas.height === 50; t.done(); - name: 2d.canvas.host.size.attributes.reflect.setidl desc: Setting IDL attributes updates IDL and content attributes code: | canvas.width = 120; canvas.height = 60; @assert canvas.width === 120; @assert canvas.height === 60; t.done(); - name: 2d.canvas.host.size.attributes.reflect.setidlzero desc: Setting IDL attributes to 0 updates IDL and content attributes code: | canvas.width = 0; canvas.height = 0; @assert canvas.width === 0; @assert canvas.height === 0; t.done(); - name: 2d.canvas.host.size.large 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; t.done();