OLD | NEW |
(Empty) | |
| 1 /* |
| 2 Distributed under both the W3C Test Suite License [1] and the W3C |
| 3 3-clause BSD License [2]. To contribute to a W3C Test Suite, see the |
| 4 policies and contribution forms [3]. |
| 5 |
| 6 [1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license |
| 7 [2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license |
| 8 [3] http://www.w3.org/2004/10/27-testcases |
| 9 */ |
| 10 |
| 11 "use strict"; |
| 12 |
| 13 var HTML5_ELEMENTS = [ 'a', 'abbr', 'address', 'area', 'article', 'aside', |
| 14 'audio', 'b', 'base', 'bdi', 'bdo', 'blockquote', 'body', 'br', |
| 15 'button', 'canvas', 'caption', 'cite', 'code', 'col', 'colgroup', |
| 16 'command', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div', |
| 17 'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', |
| 18 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', |
| 19 'hgroup', 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', |
| 20 'keygen', 'label', 'legend', 'li', 'link', 'map', 'mark', 'menu', |
| 21 'meta', 'meter', 'nav', 'noscript', 'object', 'ol', 'optgroup', |
| 22 'option', 'output', 'p', 'param', 'pre', 'progress', 'q', 'rp', 'rt', |
| 23 'ruby', 's', 'samp', 'script', 'section', 'select', 'small', 'source', |
| 24 'span', 'strong', 'style', 'sub', 'table', 'tbody', 'td', 'textarea', |
| 25 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'track', 'u', 'ul', |
| 26 'var', 'video', 'wbr' ]; |
| 27 |
| 28 var HTML5_DOCUMENT_ELEMENTS = [ 'html', 'head', 'body' ]; |
| 29 |
| 30 var HTML5_TABLE_ELEMENTS = [ 'caption', 'col', 'colgroup', 'tbody', 'td', |
| 31 'tfoot', 'th', 'thead', 'tr' ]; |
| 32 |
| 33 var EXTENDER_CHARS = [ 0x00B7, 0x02D0, 0x02D1, 0x0387, 0x0640, 0x0E46, 0x0EC6, |
| 34 0x3005, 0x3031, 0x3032, 0x3033, 0x3034, 0x3035, 0x309D, 0x309E, 0x30FC, |
| 35 0x30FD, 0x30FE ]; |
| 36 |
| 37 var COMBINING_CHARS = [ 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, |
| 38 0x0307, 0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F, |
| 39 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317, 0x0318, |
| 40 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F, 0x0320, 0x0321, |
| 41 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327, 0x0328, 0x0329, 0x032A, |
| 42 0x032B, 0x032C, 0x032D, 0x032E, 0x032F, 0x0330, 0x0331, 0x0332, 0x0333, |
| 43 0x0334, 0x0335, 0x0336, 0x0337, 0x0338, 0x0339, 0x033A, 0x033B, 0x033C, |
| 44 0x033D, 0x033E, 0x033F, 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, |
| 45 0x0360, 0x0361, 0x0483, 0x0484, 0x0485, 0x0486, 0x0591, 0x0592, 0x0593, |
| 46 0x0594, 0x0595, 0x0596, 0x0597, 0x0598, 0x0599, 0x05A0, 0x05A1, 0x05A3, |
| 47 0x05A4, 0x05A5, 0x05A6, 0x05A7, 0x05A8, 0x05A9, 0x05AA, 0x05AB, 0x05AC, |
| 48 0x05AD, 0x05AE, 0x05AF, 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, |
| 49 0x05B6, 0x05B7, 0x05B8, 0x05B9, 0x05BB, 0x05BC, 0x05BD, 0x05BF, 0x05C1, |
| 50 0x05C2, 0x05C4, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0x0650, 0x0651, |
| 51 0x0652, 0x0670, 0x06D6, 0x06D7, 0x06D8, 0x06D9, 0x06DA, 0x06DB, 0x06DC, |
| 52 0x06DD, 0x06DE, 0x06DF, 0x06E0, 0x06E1, 0x06E2, 0x06E3, 0x06E4, 0x06E7, |
| 53 0x06E8, 0x06EA, 0x06EB, 0x06EC, 0x06ED, 0x0901, 0x0902, 0x0903, 0x093C, |
| 54 0x093E, 0x093F, 0x0940, 0x0941, 0x0942, 0x0943, 0x0944, 0x0945, 0x0946, |
| 55 0x0947, 0x0948, 0x0949, 0x094A, 0x094B, 0x094C, 0x094D, 0x0951, 0x0952, |
| 56 0x0953, 0x0954, 0x0962, 0x0963, 0x0981, 0x0982, 0x0983, 0x09BC, 0x09BE, |
| 57 0x09BF, 0x09C0, 0x09C1, 0x09C2, 0x09C3, 0x09C4, 0x09C7, 0x09C8, 0x09CB, |
| 58 0x09CC, 0x09CD, 0x09D7, 0x09E2, 0x09E3, 0x0A02, 0x0A3C, 0x0A3E, 0x0A3F, |
| 59 0x0A40, 0x0A41, 0x0A42, 0x0A47, 0x0A48, 0x0A4B, 0x0A4C, 0x0A4D, 0x0A70, |
| 60 0x0A71, 0x0A81, 0x0A82, 0x0A83, 0x0ABC, 0x0ABE, 0x0ABF, 0x0AC0, 0x0AC1, |
| 61 0x0AC2, 0x0AC3, 0x0AC4, 0x0AC5, 0x0AC7, 0x0AC8, 0x0AC9, 0x0ACB, 0x0ACC, |
| 62 0x0ACD, 0x0B01, 0x0B02, 0x0B03, 0x0B3C, 0x0B3E, 0x0B3F, 0x0B40, 0x0B41, |
| 63 0x0B42, 0x0B43, 0x0B47, 0x0B48, 0x0B4B, 0x0B4C, 0x0B4D, 0x0B56, 0x0B57, |
| 64 0x0B82, 0x0B83, 0x0BBE, 0x0BBF, 0x0BC0, 0x0BC1, 0x0BC2, 0x0BC6, 0x0BC7, |
| 65 0x0BC8, 0x0BCA, 0x0BCB, 0x0BCC, 0x0BCD, 0x0BD7, 0x0C01, 0x0C02, 0x0C03, |
| 66 0x0C3E, 0x0C3F, 0x0C40, 0x0C41, 0x0C42, 0x0C43, 0x0C44, 0x0C46, 0x0C47, |
| 67 0x0C48, 0x0C4A, 0x0C4B, 0x0C4C, 0x0C4D, 0x0C55, 0x0C56, 0x0C82, 0x0C83, |
| 68 0x0CBE, 0x0CBF, 0x0CC0, 0x0CC1, 0x0CC2, 0x0CC3, 0x0CC4, 0x0CC6, 0x0CC7, |
| 69 0x0CC8, 0x0CCA, 0x0CCB, 0x0CCC, 0x0CCD, 0x0CD5, 0x0CD6, 0x0D02, 0x0D03, |
| 70 0x0D3E, 0x0D3F, 0x0D40, 0x0D41, 0x0D42, 0x0D43, 0x0D46, 0x0D47, 0x0D48, |
| 71 0x0D4A, 0x0D4B, 0x0D4C, 0x0D4D, 0x0D57, 0x0E31, 0x0E34, 0x0E35, 0x0E36, |
| 72 0x0E37, 0x0E38, 0x0E39, 0x0E3A, 0x0E47, 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, |
| 73 0x0E4C, 0x0E4D, 0x0E4E, 0x0EB1, 0x0EB4, 0x0EB5, 0x0EB6, 0x0EB7, 0x0EB8, |
| 74 0x0EB9, 0x0EBB, 0x0EBC, 0x0EC8, 0x0EC9, 0x0ECA, 0x0ECB, 0x0ECC, 0x0ECD, |
| 75 0x0F18, 0x0F19, 0x0F35, 0x0F37, 0x0F39, 0x0F3E, 0x0F3F, 0x0F71, 0x0F72, |
| 76 0x0F73, 0x0F74, 0x0F75, 0x0F76, 0x0F77, 0x0F78, 0x0F79, 0x0F7A, 0x0F7B, |
| 77 0x0F7C, 0x0F7D, 0x0F7E, 0x0F7F, 0x0F80, 0x0F81, 0x0F82, 0x0F83, 0x0F84, |
| 78 0x0F86, 0x0F87, 0x0F88, 0x0F89, 0x0F8A, 0x0F8B, 0x0F90, 0x0F91, 0x0F92, |
| 79 0x0F93, 0x0F94, 0x0F95, 0x0F97, 0x0F99, 0x0F9A, 0x0F9B, 0x0F9C, 0x0F9D, |
| 80 0x0F9E, 0x0F9F, 0x0FA0, 0x0FA1, 0x0FA2, 0x0FA3, 0x0FA4, 0x0FA5, 0x0FA6, |
| 81 0x0FA7, 0x0FA8, 0x0FA9, 0x0FAA, 0x0FAB, 0x0FAC, 0x0FAD, 0x0FB1, 0x0FB2, |
| 82 0x0FB3, 0x0FB4, 0x0FB5, 0x0FB6, 0x0FB7, 0x0FB9, 0x20D0, 0x20D1, 0x20D2, |
| 83 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x20D7, 0x20D8, 0x20D9, 0x20DA, 0x20DB, |
| 84 0x20DC, 0x20E1, 0x302A, 0x302B, 0x302C, 0x302D, 0x302E, 0x302F, 0x3099, |
| 85 0x309A ]; |
| 86 |
| 87 var BASE_CHARS_SINGLE = [ 0x0386, 0x038C, 0x03DA, 0x03DC, 0x03DE, 0x03E0, |
| 88 0x0559, 0x06D5, 0x093D, 0x09B2, 0x0A5E, 0x0A8D, 0x0ABD, 0x0AE0, 0x0B3D, |
| 89 0x0B9C, 0x0CDE, 0x0E30, 0x0E84, 0x0E8A, 0x0E8D, 0x0EA5, 0x0EA7, 0x0EB0, |
| 90 0x0EBD, 0x1100, 0x1109, 0x113C, 0x113E, 0x1140, 0x114C, 0x114E, 0x1150, |
| 91 0x1159, 0x1163, 0x1165, 0x1167, 0x1169, 0x1175, 0x119E, 0x11A8, 0x11AB, |
| 92 0x11BA, 0x11EB, 0x11F0, 0x11F9, 0x1F59, 0x1F5B, 0x1F5D, 0x1FBE, 0x2126, |
| 93 0x212E ]; |
| 94 |
| 95 var BASE_CHARS_RANGES = [ 0x0041, 0x005A, 0x0061, 0x007A, 0x00C0, 0x00D6, |
| 96 0x00D8, 0x00F6, 0x00F8, 0x00FF, 0x0100, 0x0131, 0x0134, 0x013E, 0x0141, |
| 97 0x0148, 0x014A, 0x017E, 0x0180, 0x01C3, 0x01CD, 0x01F0, 0x01F4, 0x01F5, |
| 98 0x01FA, 0x0217, 0x0250, 0x02A8, 0x02BB, 0x02C1, 0x0388, 0x038A, 0x038E, |
| 99 0x03A1, 0x03A3, 0x03CE, 0x03D0, 0x03D6, 0x03E2, 0x03F3, 0x0401, 0x040C, |
| 100 0x040E, 0x044F, 0x0451, 0x045C, 0x045E, 0x0481, 0x0490, 0x04C4, 0x04C7, |
| 101 0x04C8, 0x04CB, 0x04CC, 0x04D0, 0x04EB, 0x04EE, 0x04F5, 0x04F8, 0x04F9, |
| 102 0x0531, 0x0556, 0x0561, 0x0586, 0x05D0, 0x05EA, 0x05F0, 0x05F2, 0x0621, |
| 103 0x063A, 0x0641, 0x064A, 0x0671, 0x06B7, 0x06BA, 0x06BE, 0x06C0, 0x06CE, |
| 104 0x06D0, 0x06D3, 0x06E5, 0x06E6, 0x0905, 0x0939, 0x0958, 0x0961, 0x0985, |
| 105 0x098C, 0x098F, 0x0990, 0x0993, 0x09A8, 0x09AA, 0x09B0, 0x09B6, 0x09B9, |
| 106 0x09DC, 0x09DD, 0x09DF, 0x09E1, 0x09F0, 0x09F1, 0x0A05, 0x0A0A, 0x0A0F, |
| 107 0x0A10, 0x0A13, 0x0A28, 0x0A2A, 0x0A30, 0x0A32, 0x0A33, 0x0A35, 0x0A36, |
| 108 0x0A38, 0x0A39, 0x0A59, 0x0A5C, 0x0A72, 0x0A74, 0x0A85, 0x0A8B, 0x0A8F, |
| 109 0x0A91, 0x0A93, 0x0AA8, 0x0AAA, 0x0AB0, 0x0AB2, 0x0AB3, 0x0AB5, 0x0AB9, |
| 110 0x0B05, 0x0B0C, 0x0B0F, 0x0B10, 0x0B13, 0x0B28, 0x0B2A, 0x0B30, 0x0B32, |
| 111 0x0B33, 0x0B36, 0x0B39, 0x0B5C, 0x0B5D, 0x0B5F, 0x0B61, 0x0B85, 0x0B8A, |
| 112 0x0B8E, 0x0B90, 0x0B92, 0x0B95, 0x0B99, 0x0B9A, 0x0B9E, 0x0B9F, 0x0BA3, |
| 113 0x0BA4, 0x0BA8, 0x0BAA, 0x0BAE, 0x0BB5, 0x0BB7, 0x0BB9, 0x0C05, 0x0C0C, |
| 114 0x0C0E, 0x0C10, 0x0C12, 0x0C28, 0x0C2A, 0x0C33, 0x0C35, 0x0C39, 0x0C60, |
| 115 0x0C61, 0x0C85, 0x0C8C, 0x0C8E, 0x0C90, 0x0C92, 0x0CA8, 0x0CAA, 0x0CB3, |
| 116 0x0CB5, 0x0CB9, 0x0CE0, 0x0CE1, 0x0D05, 0x0D0C, 0x0D0E, 0x0D10, 0x0D12, |
| 117 0x0D28, 0x0D2A, 0x0D39, 0x0D60, 0x0D61, 0x0E01, 0x0E2E, 0x0E32, 0x0E33, |
| 118 0x0E40, 0x0E45, 0x0E81, 0x0E82, 0x0E87, 0x0E88, 0x0E94, 0x0E97, 0x0E99, |
| 119 0x0E9F, 0x0EA1, 0x0EA3, 0x0EAA, 0x0EAB, 0x0EAD, 0x0EAE, 0x0EB2, 0x0EB3, |
| 120 0x0EC0, 0x0EC4, 0x0F40, 0x0F47, 0x0F49, 0x0F69, 0x10A0, 0x10C5, 0x10D0, |
| 121 0x10F6, 0x1102, 0x1103, 0x1105, 0x1107, 0x110B, 0x110C, 0x110E, 0x1112, |
| 122 0x1154, 0x1155, 0x115F, 0x1161, 0x116D, 0x116E, 0x1172, 0x1173, 0x11AE, |
| 123 0x11AF, 0x11B7, 0x11B8, 0x11BC, 0x11C2, 0x1E00, 0x1E9B, 0x1EA0, 0x1EF9, |
| 124 0x1F00, 0x1F15, 0x1F18, 0x1F1D, 0x1F20, 0x1F45, 0x1F48, 0x1F4D, 0x1F50, |
| 125 0x1F57, 0x1F5F, 0x1F7D, 0x1F80, 0x1FB4, 0x1FB6, 0x1FBC, 0x1FC2, 0x1FC4, |
| 126 0x1FC6, 0x1FCC, 0x1FD0, 0x1FD3, 0x1FD6, 0x1FDB, 0x1FE0, 0x1FEC, 0x1FF2, |
| 127 0x1FF4, 0x1FF6, 0x1FFC, 0x212A, 0x212B, 0x2180, 0x2182, 0x3041, 0x3094, |
| 128 0x30A1, 0x30FA, 0x3105, 0x312C, 0xAC00, 0xD7A3 ]; |
| 129 |
| 130 var IDEOGRAPHIC_CHARS_SINGLE = [ 0x3007 ]; |
| 131 |
| 132 var IDEOGRAPHIC_CHARS_RANGES = [ 0x3021, 0x3029, 0x4E00, 0x9FA5 ]; |
| 133 |
| 134 var DIGIT_CHARS_RANGES = [ 0x0030, 0x0039, 0x0660, 0x0669, 0x06F0, 0x06F9, |
| 135 0x0966, 0x096F, 0x09E6, 0x09EF, 0x0A66, 0x0A6F, 0x0AE6, 0x0AEF, 0x0B66, |
| 136 0x0B6F, 0x0BE7, 0x0BEF, 0x0C66, 0x0C6F, 0x0CE6, 0x0CEF, 0x0D66, 0x0D6F, |
| 137 0x0E50, 0x0E59, 0x0ED0, 0x0ED9, 0x0F20, 0x0F29 ]; |
| 138 |
| 139 function CharsArray(array) { |
| 140 this.array = array; |
| 141 } |
| 142 |
| 143 CharsArray.prototype.testEach = function(namingFunction, checkFunction) { |
| 144 if (this.array != null) { |
| 145 this.array.forEach(function(value) { |
| 146 checkFunction(namingFunction(getCharCode(value))); |
| 147 }); |
| 148 } |
| 149 }; |
| 150 |
| 151 function CharRangesArray(array) { |
| 152 this.array = array; |
| 153 } |
| 154 |
| 155 CharRangesArray.prototype.testEach = function(namingFunction, checkFunction) { |
| 156 if (this.array != null) { |
| 157 for (var i = 0; i < this.array.length; i += 2) { |
| 158 var rangeStart = getCharCode(this.array[i]); |
| 159 var rangeEnd = getCharCode(this.array[i+1]); |
| 160 for (var c = rangeStart; c <= rangeEnd; c++) { |
| 161 checkFunction(namingFunction(c)); |
| 162 testCharCode(c, namingFunction, checkFunction); |
| 163 } |
| 164 } |
| 165 } |
| 166 }; |
| 167 |
| 168 function testCharCode(charCode, namingFunction, checkFunction) { |
| 169 checkFunction(namingFunction(charCode)); |
| 170 } |
| 171 |
| 172 var extenderChars = new CharsArray(EXTENDER_CHARS); |
| 173 var combiningChars = new CharsArray(COMBINING_CHARS); |
| 174 var baseCharsSingle = new CharsArray(BASE_CHARS_SINGLE); |
| 175 var baseCharsRanges = new CharRangesArray(BASE_CHARS_RANGES); |
| 176 var ideographicCharsSingle = new CharsArray(IDEOGRAPHIC_CHARS_SINGLE); |
| 177 var ideographicCharsRanges = new CharRangesArray(IDEOGRAPHIC_CHARS_RANGES); |
| 178 var digitCharsRanges = new CharRangesArray(DIGIT_CHARS_RANGES); |
| 179 |
| 180 // Helper function, which verifies that given custom element name is valid |
| 181 function checkValidName(name) { |
| 182 var doc = newHTMLDocument(); |
| 183 try { |
| 184 doc.registerElement(name); |
| 185 } catch (e) { |
| 186 assert_unreached('The custom element name \'' + name + |
| 187 '\' should be registered without errors'); |
| 188 } |
| 189 } |
| 190 |
| 191 // Helper function, which verifies that given custom element name is invalid |
| 192 function checkInvalidName(name) { |
| 193 var doc = newHTMLDocument(); |
| 194 assert_throws('SyntaxError', function() { |
| 195 doc.registerElement(name); |
| 196 }, 'Registering invalid custom element name \'' + name + '\' should fail
'); |
| 197 } |
| 198 |
| 199 // Helper function to extract character code from given object |
| 200 // expected input: either charater code or one character long string. |
| 201 function getCharCode(c) { |
| 202 if (typeof(c) === 'string') { |
| 203 assert_equals(1, c.length, 'Error in test: input string should be one ch
aracter long'); |
| 204 c = c.charCodeAt(0); |
| 205 } |
| 206 assert_equals('number', typeof(c), 'Error in test: unexpected type for chara
ter code'); |
| 207 return c; |
| 208 } |
| 209 |
| 210 var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml'; |
| 211 var SVG_NAMESPACE = 'http://www.w3.org/2000/svg'; |
| 212 |
| 213 function newHTMLDocument() { |
| 214 return document.implementation.createHTMLDocument('Test Document'); |
| 215 } |
| 216 |
| 217 // Creates new iframe and loads given url into it. |
| 218 // Returns reference to created iframe. |
| 219 function newIFrame(url) { |
| 220 assert_not_equals(url, null, 'argument url should not be null'); |
| 221 var iframe = document.createElement('iframe'); |
| 222 iframe.src = url; |
| 223 document.body.appendChild(iframe); |
| 224 return iframe; |
| 225 } |
| 226 |
| 227 // Creates new iframe and loads given url into it. |
| 228 // Function f is bound to the iframe's onload event. |
| 229 // Function f receives iframe's contentDocument as argument. |
| 230 // The iframe is disposed after function f is executed. |
| 231 function testInIFrame(url, f, testName, testProps) { |
| 232 var t = async_test(testName, testProps); |
| 233 t.step(function() { |
| 234 var iframe = newIFrame(url); |
| 235 iframe.onload = t.step_func(function() { |
| 236 try { |
| 237 f(iframe.contentDocument); |
| 238 t.done(); |
| 239 } finally { |
| 240 iframe.remove(); |
| 241 } |
| 242 }); |
| 243 }); |
| 244 } |
| 245 |
| 246 // Helper function to create a prototype for custom element |
| 247 // with predefined callbacks |
| 248 function newHTMLElementPrototype() { |
| 249 return newCustomElementPrototype(HTMLElement.prototype); |
| 250 } |
| 251 |
| 252 // Helper function to create a prototype for custom element |
| 253 // with predefined callbacks |
| 254 function newCustomElementPrototype(parent) { |
| 255 var proto = Object.create(parent); |
| 256 proto.createdCallbackThis = null; |
| 257 proto.createdCallbackCalledCounter = 0; |
| 258 |
| 259 proto.attachedCallbackThis = null; |
| 260 proto.attachedCallbackCalledCounter = 0; |
| 261 |
| 262 proto.detachedCallbackThis = null; |
| 263 proto.detachedCallbackCalledCounter = 0; |
| 264 |
| 265 proto.attributeChangedCallbackThis = null; |
| 266 proto.attributeChangedCallbackCalledCounter = 0; |
| 267 proto.attributeChangedCallbackArgs = null; |
| 268 |
| 269 proto.createdCallback = function() { |
| 270 proto.createdCallbackThis = this; |
| 271 proto.createdCallbackCalledCounter++; |
| 272 }; |
| 273 proto.attachedCallback = function() { |
| 274 proto.attachedCallbackThis = this; |
| 275 proto.attachedCallbackCalledCounter++; |
| 276 }; |
| 277 proto.detachedCallback = function() { |
| 278 proto.detachedCallbackThis = this; |
| 279 proto.detachedCallbackCalledCounter++; |
| 280 }; |
| 281 proto.attributeChangedCallback = function(arg1, arg2, arg3) { |
| 282 proto.attributeChangedCallbackThis = this; |
| 283 proto.attributeChangedCallbackCalledCounter++; |
| 284 proto.attributeChangedCallbackArgs = [arg1, arg2, arg3]; |
| 285 }; |
| 286 return proto; |
| 287 } |
OLD | NEW |