<!doctype HTML> | |
<script src="../../resources/testharness.js"></script> | |
<script src="../../resources/testharnessreport.js"></script> | |
<script> | |
// TODO(yosin): We should merge this test into | |
// "external/wpt/html/dom/reflection*.*" to avoid duplicated test cases. | |
// This test setting various attributes of a elements to JavaScript null | |
function resolve(url) | |
{ | |
var a = document.createElement('a'); | |
a.href = url; | |
return a.href; | |
} | |
function nullTestElementAttribute(elementType, element, attr) | |
{ | |
const expectedValue = attr.expectedNull; | |
test(() => { | |
if (attr.isException) { | |
assert_throws_dom(expectedValue, | |
() => element[attr.name] = null); | |
return; | |
} | |
element[attr.name] = null; | |
const actualValue = element[attr.name]; | |
if (attr.isUrl) | |
assert_equals(actualValue, resolve(expectedValue)); | |
else | |
assert_equals(actualValue, expectedValue); | |
}, `${elementType}.${attr.name}`); | |
} | |
function runTests() | |
{ | |
// Others to test: | |
// Core DOM | |
// Attr.value (expected: null) | |
// CharacterData.data | |
// ProcessingInstruction.data | |
// Functions | |
var listing = [ | |
{ | |
type: 'Node', | |
elementToUse: document.createElement('div'), | |
attributes: [ | |
{name: 'nodeValue', expectedNull: null}, | |
{name: 'textContent', expectedNull: ''} | |
] | |
}, | |
{ | |
type: 'Element', | |
elementToUse: document.createElementNS('http://example.com/', 'example'), | |
attributes: [ | |
{name: 'id', expectedNull: 'null'}, | |
{name: 'className', expectedNull: 'null'}, | |
{name: 'innerHTML', expectedNull: ''}, | |
{name: 'outerHTML', | |
expectedNull: 'NoModificationAllowedError', | |
isException: true} | |
] | |
}, | |
{ | |
type: 'HTMLElement', | |
elementToUse: document.createElement('abbr'), | |
attributes: [ | |
{name: 'accessKey', expectedNull: 'null'}, | |
{name: 'title', expectedNull: 'null'}, | |
{name: 'lang', expectedNull: 'null'}, | |
{name: 'dir', expectedNull: ''}, | |
{name: 'innerText', expectedNull: ''}, | |
{name: 'outerText', | |
expectedNull: 'NoModificationAllowedError', | |
isException: true}, | |
{name: 'contentEditable', expectedNull: 'SyntaxError', | |
isException: true} | |
] | |
}, | |
{ | |
type: 'HTMLAnchorElement', | |
elementToUse: document.createElement('a'), | |
attributes: [ | |
{name: 'charset', expectedNull: 'null'}, | |
{name: 'coords', expectedNull: 'null'}, | |
{name: 'download', expectedNull: 'null'}, | |
{name: 'href', expectedNull: 'null', isUrl: true}, | |
{name: 'hreflang', expectedNull: 'null'}, | |
{name: 'name', expectedNull: 'null'}, | |
{name: 'ping', expectedNull: 'null'}, | |
{name: 'rel', expectedNull: 'null'}, | |
{name: 'rev', expectedNull: 'null'}, | |
{name: 'shape', expectedNull: 'null'}, | |
{name: 'target', expectedNull: 'null'}, | |
{name: 'type', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLAreaElement', | |
elementToUse: document.createElement('area'), | |
attributes: [ | |
{name: 'alt', expectedNull: 'null'}, | |
{name: 'coords', expectedNull: 'null'}, | |
{name: 'href', expectedNull: 'null', isUrl: true}, | |
{name: 'ping', expectedNull: 'null'}, | |
{name: 'shape', expectedNull: 'null'}, | |
{name: 'target', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLAudioElement', | |
elementToUse: document.createElement('audio'), | |
attributes: [ | |
{name: 'preload', expectedNull: 'metadata'}, | |
{name: 'src', expectedNull: 'null', isUrl: true} | |
] | |
}, | |
{ | |
type: 'HTMLBaseElement', | |
elementToUse: document.createElement('base'), | |
attributes: [ | |
{name: 'href', expectedNull: 'null', isUrl: true}, | |
{name: 'target', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLBlockquoteElement', | |
elementToUse: document.createElement('blockquote'), | |
attributes: [ | |
{name: 'cite', expectedNull: 'null', isUrl: true} | |
] | |
}, | |
{ | |
type: 'HTMLBodyElement', | |
elementToUse: document.createElement('body'), | |
attributes: [ | |
{name: 'aLink', expectedNull: ''}, | |
{name: 'background', expectedNull: 'null'}, | |
{name: 'bgColor', expectedNull: ''}, | |
{name: 'link', expectedNull: ''}, | |
{name: 'text', expectedNull: ''}, | |
{name: 'vLink', expectedNull: ''} | |
] | |
}, | |
{ | |
type: 'HTMLBRElement', | |
elementToUse: document.createElement('br'), | |
attributes: [ | |
{name: 'clear', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLButtonElement', | |
elementToUse: document.createElement('button'), | |
attributes: [ | |
{name: 'formAction', expectedNull: 'null', isUrl: true}, | |
{name: 'formEnctype', expectedNull: 'application/x-www-form-urlencoded'}, | |
{name: 'formMethod', expectedNull: 'get'}, | |
{name: 'formTarget', expectedNull: 'null'}, | |
{name: 'name', expectedNull: 'null'}, | |
{name: 'type', expectedNull: 'submit'}, | |
{name: 'value', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLDivElement', | |
elementToUse: document.createElement('div'), | |
attributes: [ | |
{name: 'align', expectedNull: 'null'} | |
] | |
}, | |
// HTMLDListElement | |
// NONE | |
{ | |
type: 'HTMLEmbedElement', | |
elementToUse: document.createElement('embed'), | |
attributes: [ | |
{name: 'align', expectedNull: 'null'}, | |
{name: 'height', expectedNull: 'null'}, | |
{name: 'name', expectedNull: 'null'}, | |
{name: 'src', expectedNull: 'null', isUrl: true}, | |
{name: 'type', expectedNull: 'null'}, | |
{name: 'width', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLFieldSetElement', | |
elementToUse: document.createElement('fieldset'), | |
attributes: [ | |
{name: 'name', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLFontElement', | |
elementToUse: document.createElement('font'), | |
attributes: [ | |
{name: 'color', expectedNull: ''}, | |
{name: 'face', expectedNull: 'null'}, | |
{name: 'size', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLFormElement', | |
elementToUse: document.createElement('form'), | |
attributes: [ | |
{name: 'acceptCharset', expectedNull: 'null'}, | |
{name: 'action', expectedNull: 'null', isUrl: true}, | |
{name: 'autocomplete', expectedNull: 'on'}, | |
{name: 'enctype', expectedNull: 'application/x-www-form-urlencoded'}, | |
{name: 'encoding', expectedNull: 'application/x-www-form-urlencoded'}, | |
{name: 'method', expectedNull: 'get'}, | |
{name: 'name', expectedNull: 'null'}, | |
{name: 'target', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLFrameElement', | |
elementToUse: document.createElement('frame'), | |
attributes: [ | |
{name: 'frameBorder', expectedNull: 'null'}, | |
{name: 'longDesc', expectedNull: 'null', isUrl: true}, | |
{name: 'marginHeight', expectedNull: ''}, | |
{name: 'marginWidth', expectedNull: ''}, | |
{name: 'name', expectedNull: 'null'}, | |
{name: 'scrolling', expectedNull: 'null'}, | |
{name: 'src', expectedNull: 'null', isUrl: true} | |
] | |
}, | |
{ | |
type: 'HTMLFrameSetElement', | |
elementToUse: document.createElement('frameset'), | |
attributes: [ | |
{name: 'cols', expectedNull: 'null'}, | |
{name: 'rows', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLHeadingElement', | |
// no need to test h2-h6 | |
elementToUse: document.createElement('h1'), | |
attributes: [ | |
{name: 'align', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLHRElement', | |
elementToUse: document.createElement('hr'), | |
attributes: [ | |
{name: 'align', expectedNull: 'null'}, | |
{name: 'color', expectedNull: 'null'}, | |
{name: 'size', expectedNull: 'null'}, | |
{name: 'width', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLHtmlElement', | |
elementToUse: document.createElement('html'), | |
attributes: [ | |
{name: 'version', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLIFrameElement', | |
elementToUse: document.createElement('iframe'), | |
attributes: [ | |
{name: 'align', expectedNull: 'null'}, | |
{name: 'frameBorder', expectedNull: 'null'}, | |
{name: 'height', expectedNull: 'null'}, | |
{name: 'longDesc', expectedNull: 'null', isUrl: true}, | |
{name: 'marginHeight', expectedNull: ''}, | |
{name: 'marginWidth', expectedNull: ''}, | |
{name: 'name', expectedNull: 'null'}, | |
{name: 'scrolling', expectedNull: 'null'}, | |
{name: 'src', expectedNull: 'null', isUrl: true}, | |
{name: 'srcdoc', expectedNull: 'null'}, | |
{name: 'width', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLImageElement', | |
elementToUse: document.createElement('img'), | |
attributes: [ | |
{name: 'align', expectedNull: 'null'}, | |
{name: 'alt', expectedNull: 'null'}, | |
{name: 'border', expectedNull: ''}, | |
{name: 'crossOrigin', expectedNull: null}, | |
{name: 'longDesc', expectedNull: 'null', isUrl: true}, | |
{name: 'lowsrc', expectedNull: 'null', isUrl: true}, | |
{name: 'name', expectedNull: 'null'}, | |
{name: 'src', expectedNull: 'null', isUrl: true}, | |
{name: 'srcset', expectedNull: 'null'}, | |
{name: 'useMap', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLInputElement', | |
elementToUse: document.createElement('input'), | |
attributes: [ | |
{name: 'accept', expectedNull: 'null'}, | |
{name: 'align', expectedNull: 'null'}, | |
{name: 'alt', expectedNull: 'null'}, | |
{name: 'autocomplete', expectedNull: ''}, | |
{name: 'defaultValue', expectedNull: 'null'}, | |
{name: 'dirName', expectedNull: 'null'}, | |
{name: 'formAction', expectedNull: 'null', isUrl: true}, | |
{name: 'formEnctype', expectedNull: 'application/x-www-form-urlencoded'}, | |
{name: 'formMethod', expectedNull: 'get'}, | |
{name: 'formTarget', expectedNull: 'null'}, | |
{name: 'max', expectedNull: 'null'}, | |
{name: 'min', expectedNull: 'null'}, | |
{name: 'name', expectedNull: 'null'}, | |
{name: 'pattern', expectedNull: 'null'}, | |
{name: 'placeholder', expectedNull: 'null'}, | |
{name: 'src', expectedNull: 'null', isUrl: true}, | |
{name: 'step', expectedNull: 'null'}, | |
{name: 'type', expectedNull: 'text'}, | |
{name: 'useMap', expectedNull: 'null'} | |
] | |
}, | |
// [TreatNullAs=NullString] is not identical to [TreatNullAs=EmptyString] because | |
// null and empty string can be distinguished. A side-effect is that setting | |
// HTMLInputElement.value to null does clear the old value. This would be fixed by | |
// using [TreatNullAs=EmptyString], but until then test value separately to avoid | |
// interference from the defaultValue test. | |
{ | |
type: 'HTMLInputElement', | |
elementToUse: document.createElement('input'), | |
attributes: [ | |
{name: 'value', expectedNull: ''} | |
] | |
}, | |
{ | |
type: 'HTMLLabelElement', | |
elementToUse: document.createElement('label'), | |
attributes: [ | |
{name: 'htmlFor', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLLegendElement', | |
elementToUse: document.createElement('legend'), | |
attributes: [ | |
{name: 'align', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLLIElement', | |
elementToUse: document.createElement('li'), | |
attributes: [ | |
{name: 'type', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLLinkElement', | |
elementToUse: document.createElement('link'), | |
attributes: [ | |
{name: 'charset', expectedNull: 'null'}, | |
{name: 'href', expectedNull: 'null', isUrl: true}, | |
{name: 'hreflang', expectedNull: 'null'}, | |
{name: 'media', expectedNull: 'null'}, | |
{name: 'rel', expectedNull: 'null'}, | |
{name: 'rev', expectedNull: 'null'}, | |
{name: 'target', expectedNull: 'null'}, | |
{name: 'type', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLMapElement', | |
elementToUse: document.createElement('map'), | |
attributes: [ | |
{name: 'name', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLMarqueeElement', | |
elementToUse: document.createElement('marquee'), | |
attributes: [ | |
{name: 'behavior', expectedNull: 'null'}, | |
{name: 'bgColor', expectedNull: 'null'}, | |
{name: 'direction', expectedNull: 'null'}, | |
{name: 'height', expectedNull: 'null'}, | |
{name: 'width', expectedNull: 'null'} | |
] | |
}, | |
// HTMLMenuElement | |
// NONE | |
{ | |
type: 'HTMLMetaElement', | |
elementToUse: document.createElement('meta'), | |
attributes: [ | |
{name: 'content', expectedNull: 'null'}, | |
{name: 'httpEquiv', expectedNull: 'null'}, | |
{name: 'name', expectedNull: 'null'}, | |
{name: 'scheme', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLModElement', | |
elementToUse: document.createElement('ins'), // same as 'del' | |
attributes: [ | |
{name: 'cite', expectedNull: 'null', isUrl: true}, | |
{name: 'dateTime', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLObjectElement', | |
elementToUse: document.createElement('object'), | |
attributes: [ | |
{name: 'code', expectedNull: 'null'}, | |
{name: 'align', expectedNull: 'null'}, | |
{name: 'archive', expectedNull: 'null'}, | |
{name: 'border', expectedNull: ''}, | |
{name: 'codeBase', expectedNull: 'null', isUrl: true}, | |
{name: 'codeType', expectedNull: 'null'}, | |
{name: 'data', expectedNull: 'null', isUrl: true}, | |
{name: 'height', expectedNull: 'null'}, | |
{name: 'name', expectedNull: 'null'}, | |
{name: 'standby', expectedNull: 'null'}, | |
{name: 'type', expectedNull: 'null'}, | |
{name: 'useMap', expectedNull: 'null'}, | |
{name: 'width', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLOListElement', | |
elementToUse: document.createElement('ol'), | |
attributes: [ | |
{name: 'type', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLOptGroupElement', | |
elementToUse: document.createElement('optgroup'), | |
attributes: [ | |
{name: 'label', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLOptionElement', | |
elementToUse: document.createElement('option'), | |
attributes: [ | |
{name: 'text', expectedNull: 'null'}, | |
{name: 'label', expectedNull: 'null'}, | |
{name: 'value', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLOutputElement', | |
elementToUse: document.createElement('output'), | |
attributes: [ | |
{name: 'name', expectedNull: 'null'}, | |
{name: 'defaultValue', expectedNull: 'null'}, | |
{name: 'value', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLParagraphElement', | |
elementToUse: document.createElement('p'), | |
attributes: [ | |
{name: 'align', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLParamElement', | |
elementToUse: document.createElement('param'), | |
attributes: [ | |
{name: 'name', expectedNull: 'null'}, | |
{name: 'type', expectedNull: 'null'}, | |
{name: 'value', expectedNull: 'null'}, | |
{name: 'valueType', expectedNull: 'null'} | |
] | |
}, | |
// HTMLPreElement | |
// NONE | |
{ | |
type: 'HTMLQuoteElement', | |
elementToUse: document.createElement('q'), | |
attributes: [ | |
{name: 'cite', expectedNull: 'null', isUrl:true} | |
] | |
}, | |
{ | |
type: 'HTMLScriptElement', | |
elementToUse: document.createElement('script'), | |
attributes: [ | |
{name: 'text', expectedNull: 'null'}, | |
{name: 'htmlFor', expectedNull: 'null'}, | |
{name: 'event', expectedNull: 'null'}, | |
{name: 'charset', expectedNull: 'null'}, | |
{name: 'src', expectedNull: 'null', isUrl: true}, | |
{name: 'type', expectedNull: 'null'}, | |
{name: 'crossOrigin', expectedNull: null} | |
] | |
}, | |
{ | |
type: 'HTMLSelectElement', | |
elementToUse: document.createElement('select'), | |
attributes: [ | |
{name: 'value', expectedNull: ''}, | |
{name: 'name', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLSourceElement', | |
elementToUse: document.createElement('source'), | |
attributes: [ | |
{name: 'src', expectedNull: 'null', isUrl: true}, | |
{name: 'type', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLStyleElement', | |
elementToUse: document.createElement('style'), | |
attributes: [ | |
{name: 'media', expectedNull: 'null'}, | |
{name: 'type', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLTableCaptionElement', | |
elementToUse: document.createElement('caption'), | |
attributes: [ | |
{name: 'align', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLTableCellElement', | |
elementToUse: document.createElement('td'), | |
attributes: [ | |
{name: 'abbr', expectedNull: 'null'}, | |
{name: 'align', expectedNull: 'null'}, | |
{name: 'axis', expectedNull: 'null'}, | |
{name: 'bgColor', expectedNull: ''}, | |
{name: 'ch', expectedNull: 'null'}, | |
{name: 'chOff', expectedNull: 'null'}, | |
{name: 'headers', expectedNull: 'null'}, | |
{name: 'height', expectedNull: 'null'}, | |
{name: 'scope', expectedNull: ''}, | |
{name: 'vAlign', expectedNull: 'null'}, | |
{name: 'width', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLTableColElement', | |
elementToUse: document.createElement('col'), | |
attributes: [ | |
{name: 'align', expectedNull: 'null'}, | |
{name: 'ch', expectedNull: 'null'}, | |
{name: 'chOff', expectedNull: 'null'}, | |
{name: 'vAlign', expectedNull: 'null'}, | |
{name: 'width', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLTableElement', | |
elementToUse: document.createElement('table'), | |
attributes: [ | |
{name: 'align', expectedNull: 'null'}, | |
{name: 'bgColor', expectedNull: ''}, | |
{name: 'border', expectedNull: 'null'}, | |
{name: 'cellPadding', expectedNull: ''}, | |
{name: 'cellSpacing', expectedNull: ''}, | |
{name: 'frame', expectedNull: 'null'}, | |
{name: 'rules', expectedNull: 'null'}, | |
{name: 'summary', expectedNull: 'null'}, | |
{name: 'width', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLTableRowElement', | |
elementToUse: document.createElement('tr'), | |
attributes: [ | |
{name: 'align', expectedNull: 'null'}, | |
{name: 'bgColor', expectedNull: ''}, | |
{name: 'ch', expectedNull: 'null'}, | |
{name: 'chOff', expectedNull: 'null'}, | |
{name: 'vAlign', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLTableSectionElement', | |
elementToUse: document.createElement('tbody'), | |
attributes: [ | |
{name: 'align', expectedNull: 'null'}, | |
{name: 'ch', expectedNull: 'null'}, | |
{name: 'chOff', expectedNull: 'null'}, | |
{name: 'vAlign', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLTextAreaElement', | |
elementToUse: document.createElement('textarea'), | |
attributes: [ | |
{name: 'defaultValue', expectedNull: 'null'}, | |
{name: 'dirName', expectedNull: 'null'}, | |
{name: 'name', expectedNull: 'null'}, | |
{name: 'placeholder', expectedNull: 'null'}, | |
{name: 'value', expectedNull: ''}, | |
{name: 'wrap', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLTitleElement', | |
elementToUse: document.createElement('title'), | |
attributes: [ | |
{name: 'text', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLTrackElement', | |
elementToUse: document.createElement('track'), | |
attributes: [ | |
{name: 'kind', expectedNull: 'metadata'}, | |
{name: 'label', expectedNull: 'null'}, | |
{name: 'src', expectedNull: 'null', isUrl: true}, | |
{name: 'srclang', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLUListElement', | |
elementToUse: document.createElement('ul'), | |
attributes: [ | |
{name: 'type', expectedNull: 'null'} | |
] | |
}, | |
{ | |
type: 'HTMLVideoElement', | |
elementToUse: document.createElement('video'), | |
attributes: [ | |
{name: 'poster', expectedNull: 'null', isUrl: true}, | |
{name: 'preload', expectedNull: 'metadata'}, | |
{name: 'src', expectedNull: 'null', isUrl: true} | |
] | |
} | |
]; | |
for (const {type, elementToUse, attributes} of listing) { | |
for (const attr of attributes) | |
nullTestElementAttribute(type, elementToUse, attr); | |
} | |
} | |
runTests(); | |
</script> |