• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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