1/* 2* Copyright (c) Microsoft Corporation. All rights reserved. 3* Copyright (c) 2023 Huawei Device Co., Ltd. 4* Licensed under the Apache License, Version 2.0 (the "License"); 5* you may not use this file except in compliance with the License. 6* You may obtain a copy of the License at 7* 8* http://www.apache.org/licenses/LICENSE-2.0 9* 10* Unless required by applicable law or agreed to in writing, software 11* distributed under the License is distributed on an "AS IS" BASIS, 12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13* See the License for the specific language governing permissions and 14* limitations under the License. 15* 16* This file has been modified by Huawei to verify type inference by adding verification statements. 17*/ 18 19// === tests/cases/compiler/controlFlowPropertyDeclarations.ts === 20declare function AssertType(value:any, type:string):void; 21// Repro from ##8913 22 23declare let require:any; 24AssertType(require, "any"); 25 26let HTMLDOMPropertyConfig = require('react/lib/HTMLDOMPropertyConfig'); 27AssertType(HTMLDOMPropertyConfig, "any"); 28AssertType(require('react/lib/HTMLDOMPropertyConfig'), "any"); 29AssertType(require, "any"); 30AssertType('react/lib/HTMLDOMPropertyConfig', "string"); 31 32// Populate property map with ReactJS's attribute and property mappings 33// TODO handle/use .Properties value eg: MUST_USE_PROPERTY is not HTML attr 34for (let propname in HTMLDOMPropertyConfig.Properties) { 35 if (!HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname)) { 36AssertType(!HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname), "boolean"); 37AssertType(HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname), "any"); 38AssertType(HTMLDOMPropertyConfig.Properties.hasOwnProperty, "any"); 39AssertType(HTMLDOMPropertyConfig.Properties, "any"); 40AssertType(propname, "string"); 41 42 continue; 43 } 44 45 let mapFrom = HTMLDOMPropertyConfig.DOMAttributeNames[propname] || propname.toLowerCase(); 46AssertType(mapFrom, "any"); 47AssertType(HTMLDOMPropertyConfig.DOMAttributeNames[propname] || propname.toLowerCase(), "any"); 48AssertType(HTMLDOMPropertyConfig.DOMAttributeNames[propname], "any"); 49AssertType(HTMLDOMPropertyConfig.DOMAttributeNames, "any"); 50AssertType(propname, "string"); 51AssertType(propname.toLowerCase(), "string"); 52AssertType(propname.toLowerCase, "() => string"); 53} 54 55/** 56 * Repeats a string a certain number of times. 57 * Also: the future is bright and consists of native string repetition: 58 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat 59 * 60 * @param {string} string String to repeat 61 * @param {number} times Number of times to repeat string. Integer. 62 * @see http://jsperf.com/string-repeater/2 63 */ 64function repeatString(string, times) { 65 if (times === 1) { 66AssertType(times === 1, "boolean"); 67AssertType(times, "any"); 68AssertType(1, "int"); 69 70AssertType(string, "any"); 71 return string; 72 } 73 if (times < 0) { throw new Error(); 74AssertType(times < 0, "boolean"); 75 76AssertType(times, "any"); 77 78AssertType(0, "int"); 79 80AssertType(new Error(), "Error"); 81 82AssertType(Error, "ErrorConstructor"); 83} 84 85 let repeated = ''; 86AssertType(repeated, "string"); 87AssertType('', "string"); 88 89 while (times) { 90AssertType(times, "any"); 91 92 if (times & 1) { 93AssertType(times & 1, "number"); 94AssertType(times, "any"); 95AssertType(1, "int"); 96 97 repeated += string; 98AssertType(repeated += string, "string"); 99AssertType(repeated, "string"); 100AssertType(string, "any"); 101 } 102 if (times >>= 1) { 103AssertType(times >>= 1, "number"); 104AssertType(times, "any"); 105AssertType(1, "int"); 106 107 string += string; 108AssertType(string += string, "any"); 109AssertType(string, "any"); 110AssertType(string, "any"); 111 } 112 } 113AssertType(repeated, "string"); 114 return repeated; 115} 116 117/** 118 * Determine if the string ends with the specified substring. 119 * 120 * @param {string} haystack String to search in 121 * @param {string} needle String to search for 122 * @ 123return {boolean} 124 */ 125function endsWith(haystack, needle) { 126AssertType(haystack.slice(-needle.length) === needle, "boolean"); 127AssertType(haystack.slice(-needle.length), "any"); 128AssertType(haystack.slice, "any"); 129AssertType(-needle.length, "number"); 130AssertType(needle.length, "any"); 131AssertType(needle, "any"); 132 return haystack.slice(-needle.length) === needle; 133} 134 135/** 136 * Trim the specified substring off the string. If the string does not end 137 * with the specified substring, this is a no-op. 138 * 139 * @param {string} haystack String to search in 140 * @param {string} needle String to search for 141 * @ 142return {string} 143 */ 144function trimEnd(haystack, needle) { 145AssertType(endsWith(haystack, needle) ? haystack.slice(0, -needle.length) : haystack, "any"); 146AssertType(endsWith(haystack, needle), "boolean"); 147AssertType(endsWith, "(any, any) => boolean"); 148AssertType(haystack, "any"); 149AssertType(needle, "any"); 150 return endsWith(haystack, needle) 151 152 ? haystack.slice(0, -needle.length) 153AssertType(haystack.slice(0, -needle.length), "any"); 154AssertType(haystack.slice, "any"); 155AssertType(0, "int"); 156AssertType(-needle.length, "number"); 157AssertType(needle.length, "any"); 158 159 : haystack; 160AssertType(haystack, "any"); 161} 162 163/** 164 * Convert a hyphenated string to camelCase. 165 */ 166function hyphenToCamelCase(string) { 167AssertType(string.replace(/-(.)/g, function(match, chr) { return chr.toUpperCase(); }), "any"); 168AssertType(string.replace, "any"); 169AssertType(/-(.)/g, "RegExp"); 170AssertType(function(match, chr) { return chr.toUpperCase(); }, "(any, any) => any"); 171AssertType(match, "any"); 172AssertType(chr, "any"); 173 return string.replace(/-(.)/g, function(match, chr) { 174 175AssertType(chr.toUpperCase(), "any"); 176AssertType(chr.toUpperCase, "any"); 177 return chr.toUpperCase(); 178 179 }); 180} 181 182/** 183 * Determines if the specified string consists entirely of whitespace. 184 */ 185function isEmpty(string) { 186AssertType(!/[^\s]/.test(string), "boolean"); 187AssertType(/[^\s]/.test(string), "boolean"); 188AssertType(/[^\s]/.test, "(string) => boolean"); 189AssertType(/[^\s]/, "RegExp"); 190AssertType(string, "any"); 191 return !/[^\s]/.test(string); 192} 193 194/** 195 * Determines if the CSS value can be converted from a 196 * 'px' suffixed string to a numeric value 197 * 198 * @param {string} value CSS property value 199 * @ 200return {boolean} 201 */ 202function isConvertiblePixelValue(value) { 203AssertType(/^\d+px$/.test(value), "boolean"); 204AssertType(/^\d+px$/.test, "(string) => boolean"); 205AssertType(/^\d+px$/, "RegExp"); 206AssertType(value, "any"); 207 return /^\d+px$/.test(value); 208} 209 210export class HTMLtoJSX { 211 private output: string; 212 private level: number; 213 private _inPreTag: boolean; 214 215 216 /** 217 * Handles processing of the specified text node 218 * 219 * @param {TextNode} node 220 */ 221 _visitText = (node) => { 222 let parentTag = node.parentNode && node.parentNode.tagName.toLowerCase(); 223AssertType(parentTag, "any"); 224AssertType(node.parentNode && node.parentNode.tagName.toLowerCase(), "any"); 225AssertType(node.parentNode, "any"); 226AssertType(node.parentNode.tagName.toLowerCase(), "any"); 227AssertType(node.parentNode.tagName.toLowerCase, "any"); 228AssertType(node.parentNode.tagName, "any"); 229AssertType(node.parentNode, "any"); 230 231 if (parentTag === 'textarea' || parentTag === 'style') { 232AssertType(parentTag === 'textarea' || parentTag === 'style', "boolean"); 233AssertType(parentTag === 'textarea', "boolean"); 234AssertType(parentTag, "any"); 235AssertType('textarea', "string"); 236AssertType(parentTag === 'style', "boolean"); 237AssertType(parentTag, "any"); 238AssertType('style', "string"); 239 240 // Ignore text content of textareas and styles, as it will have already been moved 241 // to a "defaultValue" attribute and "dangerouslySetInnerHTML" attribute respectively. 242 return; 243 } 244 245 let text = '' 246AssertType(text, "string"); 247AssertType('', "string"); 248 249 if (this._inPreTag) { 250AssertType(this._inPreTag, "boolean"); 251AssertType(this, "this"); 252 253 // If this text is contained within a <pre>, we need to ensure the JSX 254 // whitespace coalescing rules don't eat the whitespace. This means 255 // wrapping newlines and sequences of two or more spaces in letiables. 256 text = text 257AssertType(text, "string"); 258AssertType(text .replace(/\r/g, '') .replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) { return '{' + JSON.stringify(whitespace) + '}'; }), "string"); 259AssertType(text .replace(/\r/g, '') .replace, "{ (union, string): string; (union, (string, ...any[]) => string): string; }"); 260AssertType(text .replace(/\r/g, ''), "string"); 261AssertType(text .replace, "{ (union, string): string; (union, (string, ...any[]) => string): string; }"); 262AssertType(text = text .replace(/\r/g, '') .replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) { return '{' + JSON.stringify(whitespace) + '}'; }), "string"); 263 264 .replace(/\r/g, '') 265AssertType(/\r/g, "RegExp"); 266AssertType('', "string"); 267 268 .replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) { 269AssertType(/( {2,}|\n|\t|\{|\})/g, "RegExp"); 270AssertType(whitespace, "string"); 271AssertType(function(whitespace) { return '{' + JSON.stringify(whitespace) + '}'; }, "(string) => string"); 272 273AssertType('{' + JSON.stringify(whitespace) + '}', "string"); 274AssertType('{' + JSON.stringify(whitespace), "string"); 275AssertType('{', "string"); 276AssertType(JSON.stringify(whitespace), "string"); 277AssertType(JSON.stringify, "{ (any, ?(any, string, any) => any, ?union): string; (any, ?(union)[], ?union): string; }"); 278AssertType(whitespace, "string"); 279AssertType('}', "string"); 280 return '{' + JSON.stringify(whitespace) + '}'; 281 282 }); 283 } else { 284 // If there's a newline in the text, adjust the indent level 285 if (text.indexOf('\n') > -1) { 286AssertType(text.indexOf('\n') > -1, "boolean"); 287AssertType(text.indexOf('\n'), "number"); 288AssertType(text.indexOf, "(string, ?number) => number"); 289AssertType('\n', "string"); 290AssertType(-1, "int"); 291AssertType(1, "int"); 292 } 293 } 294 this.output += text; 295AssertType(this.output += text, "string"); 296AssertType(this.output, "string"); 297AssertType(this, "this"); 298AssertType(text, "string"); 299 } 300 301 302 303}; 304 305/** 306 * Handles parsing of inline styles 307 */ 308export class StyleParser { 309 styles = {}; 310 toJSXString = () => { 311 for (let key in this.styles) { 312AssertType(key, "string"); 313AssertType(this.styles, "{}"); 314AssertType(this, "this"); 315 316 if (!this.styles.hasOwnProperty(key)) { 317AssertType(!this.styles.hasOwnProperty(key), "boolean"); 318AssertType(this.styles.hasOwnProperty(key), "boolean"); 319AssertType(this.styles.hasOwnProperty, "(PropertyKey) => boolean"); 320AssertType(this.styles, "{}"); 321AssertType(this, "this"); 322AssertType(key, "string"); 323 } 324 } 325 } 326} 327 328