Merge pull request #8941 from Microsoft/controlFlowPropertyDeclarations

Create control flows for property declarations
This commit is contained in:
Anders Hejlsberg 2016-06-02 09:21:49 -07:00
commit 9f087cb62a
5 changed files with 1112 additions and 0 deletions

View file

@ -1142,6 +1142,8 @@ namespace ts {
case SyntaxKind.ModuleBlock:
return ContainerFlags.IsControlFlowContainer;
case SyntaxKind.PropertyDeclaration:
return (<PropertyDeclaration>node).initializer ? ContainerFlags.IsControlFlowContainer : 0;
case SyntaxKind.CatchClause:
case SyntaxKind.ForStatement:

View file

@ -0,0 +1,291 @@
//// [controlFlowPropertyDeclarations.ts]
// Repro from ##8913
declare var require:any;
var HTMLDOMPropertyConfig = require('react/lib/HTMLDOMPropertyConfig');
// Populate property map with ReactJS's attribute and property mappings
// TODO handle/use .Properties value eg: MUST_USE_PROPERTY is not HTML attr
for (var propname in HTMLDOMPropertyConfig.Properties) {
if (!HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname)) {
continue;
}
var mapFrom = HTMLDOMPropertyConfig.DOMAttributeNames[propname] || propname.toLowerCase();
}
/**
* Repeats a string a certain number of times.
* Also: the future is bright and consists of native string repetition:
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
*
* @param {string} string String to repeat
* @param {number} times Number of times to repeat string. Integer.
* @see http://jsperf.com/string-repeater/2
*/
function repeatString(string, times) {
if (times === 1) {
return string;
}
if (times < 0) { throw new Error(); }
var repeated = '';
while (times) {
if (times & 1) {
repeated += string;
}
if (times >>= 1) {
string += string;
}
}
return repeated;
}
/**
* Determine if the string ends with the specified substring.
*
* @param {string} haystack String to search in
* @param {string} needle String to search for
* @return {boolean}
*/
function endsWith(haystack, needle) {
return haystack.slice(-needle.length) === needle;
}
/**
* Trim the specified substring off the string. If the string does not end
* with the specified substring, this is a no-op.
*
* @param {string} haystack String to search in
* @param {string} needle String to search for
* @return {string}
*/
function trimEnd(haystack, needle) {
return endsWith(haystack, needle)
? haystack.slice(0, -needle.length)
: haystack;
}
/**
* Convert a hyphenated string to camelCase.
*/
function hyphenToCamelCase(string) {
return string.replace(/-(.)/g, function(match, chr) {
return chr.toUpperCase();
});
}
/**
* Determines if the specified string consists entirely of whitespace.
*/
function isEmpty(string) {
return !/[^\s]/.test(string);
}
/**
* Determines if the CSS value can be converted from a
* 'px' suffixed string to a numeric value
*
* @param {string} value CSS property value
* @return {boolean}
*/
function isConvertiblePixelValue(value) {
return /^\d+px$/.test(value);
}
export class HTMLtoJSX {
private output: string;
private level: number;
private _inPreTag: boolean;
/**
* Handles processing of the specified text node
*
* @param {TextNode} node
*/
_visitText = (node) => {
var parentTag = node.parentNode && node.parentNode.tagName.toLowerCase();
if (parentTag === 'textarea' || parentTag === 'style') {
// Ignore text content of textareas and styles, as it will have already been moved
// to a "defaultValue" attribute and "dangerouslySetInnerHTML" attribute respectively.
return;
}
var text = ''
if (this._inPreTag) {
// If this text is contained within a <pre>, we need to ensure the JSX
// whitespace coalescing rules don't eat the whitespace. This means
// wrapping newlines and sequences of two or more spaces in variables.
text = text
.replace(/\r/g, '')
.replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) {
return '{' + JSON.stringify(whitespace) + '}';
});
} else {
// If there's a newline in the text, adjust the indent level
if (text.indexOf('\n') > -1) {
}
}
this.output += text;
}
};
/**
* Handles parsing of inline styles
*/
export class StyleParser {
styles = {};
toJSXString = () => {
for (var key in this.styles) {
if (!this.styles.hasOwnProperty(key)) {
}
}
}
}
//// [controlFlowPropertyDeclarations.js]
// Repro from ##8913
"use strict";
var HTMLDOMPropertyConfig = require('react/lib/HTMLDOMPropertyConfig');
// Populate property map with ReactJS's attribute and property mappings
// TODO handle/use .Properties value eg: MUST_USE_PROPERTY is not HTML attr
for (var propname in HTMLDOMPropertyConfig.Properties) {
if (!HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname)) {
continue;
}
var mapFrom = HTMLDOMPropertyConfig.DOMAttributeNames[propname] || propname.toLowerCase();
}
/**
* Repeats a string a certain number of times.
* Also: the future is bright and consists of native string repetition:
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
*
* @param {string} string String to repeat
* @param {number} times Number of times to repeat string. Integer.
* @see http://jsperf.com/string-repeater/2
*/
function repeatString(string, times) {
if (times === 1) {
return string;
}
if (times < 0) {
throw new Error();
}
var repeated = '';
while (times) {
if (times & 1) {
repeated += string;
}
if (times >>= 1) {
string += string;
}
}
return repeated;
}
/**
* Determine if the string ends with the specified substring.
*
* @param {string} haystack String to search in
* @param {string} needle String to search for
* @return {boolean}
*/
function endsWith(haystack, needle) {
return haystack.slice(-needle.length) === needle;
}
/**
* Trim the specified substring off the string. If the string does not end
* with the specified substring, this is a no-op.
*
* @param {string} haystack String to search in
* @param {string} needle String to search for
* @return {string}
*/
function trimEnd(haystack, needle) {
return endsWith(haystack, needle)
? haystack.slice(0, -needle.length)
: haystack;
}
/**
* Convert a hyphenated string to camelCase.
*/
function hyphenToCamelCase(string) {
return string.replace(/-(.)/g, function (match, chr) {
return chr.toUpperCase();
});
}
/**
* Determines if the specified string consists entirely of whitespace.
*/
function isEmpty(string) {
return !/[^\s]/.test(string);
}
/**
* Determines if the CSS value can be converted from a
* 'px' suffixed string to a numeric value
*
* @param {string} value CSS property value
* @return {boolean}
*/
function isConvertiblePixelValue(value) {
return /^\d+px$/.test(value);
}
var HTMLtoJSX = (function () {
function HTMLtoJSX() {
var _this = this;
/**
* Handles processing of the specified text node
*
* @param {TextNode} node
*/
this._visitText = function (node) {
var parentTag = node.parentNode && node.parentNode.tagName.toLowerCase();
if (parentTag === 'textarea' || parentTag === 'style') {
// Ignore text content of textareas and styles, as it will have already been moved
// to a "defaultValue" attribute and "dangerouslySetInnerHTML" attribute respectively.
return;
}
var text = '';
if (_this._inPreTag) {
// If this text is contained within a <pre>, we need to ensure the JSX
// whitespace coalescing rules don't eat the whitespace. This means
// wrapping newlines and sequences of two or more spaces in variables.
text = text
.replace(/\r/g, '')
.replace(/( {2,}|\n|\t|\{|\})/g, function (whitespace) {
return '{' + JSON.stringify(whitespace) + '}';
});
}
else {
// If there's a newline in the text, adjust the indent level
if (text.indexOf('\n') > -1) {
}
}
_this.output += text;
};
}
return HTMLtoJSX;
}());
exports.HTMLtoJSX = HTMLtoJSX;
;
/**
* Handles parsing of inline styles
*/
var StyleParser = (function () {
function StyleParser() {
var _this = this;
this.styles = {};
this.toJSXString = function () {
for (var key in _this.styles) {
if (!_this.styles.hasOwnProperty(key)) {
}
}
};
}
return StyleParser;
}());
exports.StyleParser = StyleParser;

View file

@ -0,0 +1,288 @@
=== tests/cases/compiler/controlFlowPropertyDeclarations.ts ===
// Repro from ##8913
declare var require:any;
>require : Symbol(require, Decl(controlFlowPropertyDeclarations.ts, 2, 11))
var HTMLDOMPropertyConfig = require('react/lib/HTMLDOMPropertyConfig');
>HTMLDOMPropertyConfig : Symbol(HTMLDOMPropertyConfig, Decl(controlFlowPropertyDeclarations.ts, 4, 3))
>require : Symbol(require, Decl(controlFlowPropertyDeclarations.ts, 2, 11))
// Populate property map with ReactJS's attribute and property mappings
// TODO handle/use .Properties value eg: MUST_USE_PROPERTY is not HTML attr
for (var propname in HTMLDOMPropertyConfig.Properties) {
>propname : Symbol(propname, Decl(controlFlowPropertyDeclarations.ts, 8, 8))
>HTMLDOMPropertyConfig : Symbol(HTMLDOMPropertyConfig, Decl(controlFlowPropertyDeclarations.ts, 4, 3))
if (!HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname)) {
>HTMLDOMPropertyConfig : Symbol(HTMLDOMPropertyConfig, Decl(controlFlowPropertyDeclarations.ts, 4, 3))
>propname : Symbol(propname, Decl(controlFlowPropertyDeclarations.ts, 8, 8))
continue;
}
var mapFrom = HTMLDOMPropertyConfig.DOMAttributeNames[propname] || propname.toLowerCase();
>mapFrom : Symbol(mapFrom, Decl(controlFlowPropertyDeclarations.ts, 13, 5))
>HTMLDOMPropertyConfig : Symbol(HTMLDOMPropertyConfig, Decl(controlFlowPropertyDeclarations.ts, 4, 3))
>propname : Symbol(propname, Decl(controlFlowPropertyDeclarations.ts, 8, 8))
>propname.toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --))
>propname : Symbol(propname, Decl(controlFlowPropertyDeclarations.ts, 8, 8))
>toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --))
}
/**
* Repeats a string a certain number of times.
* Also: the future is bright and consists of native string repetition:
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
*
* @param {string} string String to repeat
* @param {number} times Number of times to repeat string. Integer.
* @see http://jsperf.com/string-repeater/2
*/
function repeatString(string, times) {
>repeatString : Symbol(repeatString, Decl(controlFlowPropertyDeclarations.ts, 14, 1))
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 25, 22))
>times : Symbol(times, Decl(controlFlowPropertyDeclarations.ts, 25, 29))
if (times === 1) {
>times : Symbol(times, Decl(controlFlowPropertyDeclarations.ts, 25, 29))
return string;
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 25, 22))
}
if (times < 0) { throw new Error(); }
>times : Symbol(times, Decl(controlFlowPropertyDeclarations.ts, 25, 29))
>Error : Symbol(Error, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
var repeated = '';
>repeated : Symbol(repeated, Decl(controlFlowPropertyDeclarations.ts, 30, 5))
while (times) {
>times : Symbol(times, Decl(controlFlowPropertyDeclarations.ts, 25, 29))
if (times & 1) {
>times : Symbol(times, Decl(controlFlowPropertyDeclarations.ts, 25, 29))
repeated += string;
>repeated : Symbol(repeated, Decl(controlFlowPropertyDeclarations.ts, 30, 5))
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 25, 22))
}
if (times >>= 1) {
>times : Symbol(times, Decl(controlFlowPropertyDeclarations.ts, 25, 29))
string += string;
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 25, 22))
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 25, 22))
}
}
return repeated;
>repeated : Symbol(repeated, Decl(controlFlowPropertyDeclarations.ts, 30, 5))
}
/**
* Determine if the string ends with the specified substring.
*
* @param {string} haystack String to search in
* @param {string} needle String to search for
* @return {boolean}
*/
function endsWith(haystack, needle) {
>endsWith : Symbol(endsWith, Decl(controlFlowPropertyDeclarations.ts, 40, 1))
>haystack : Symbol(haystack, Decl(controlFlowPropertyDeclarations.ts, 49, 18))
>needle : Symbol(needle, Decl(controlFlowPropertyDeclarations.ts, 49, 27))
return haystack.slice(-needle.length) === needle;
>haystack : Symbol(haystack, Decl(controlFlowPropertyDeclarations.ts, 49, 18))
>needle : Symbol(needle, Decl(controlFlowPropertyDeclarations.ts, 49, 27))
>needle : Symbol(needle, Decl(controlFlowPropertyDeclarations.ts, 49, 27))
}
/**
* Trim the specified substring off the string. If the string does not end
* with the specified substring, this is a no-op.
*
* @param {string} haystack String to search in
* @param {string} needle String to search for
* @return {string}
*/
function trimEnd(haystack, needle) {
>trimEnd : Symbol(trimEnd, Decl(controlFlowPropertyDeclarations.ts, 51, 1))
>haystack : Symbol(haystack, Decl(controlFlowPropertyDeclarations.ts, 61, 17))
>needle : Symbol(needle, Decl(controlFlowPropertyDeclarations.ts, 61, 26))
return endsWith(haystack, needle)
>endsWith : Symbol(endsWith, Decl(controlFlowPropertyDeclarations.ts, 40, 1))
>haystack : Symbol(haystack, Decl(controlFlowPropertyDeclarations.ts, 61, 17))
>needle : Symbol(needle, Decl(controlFlowPropertyDeclarations.ts, 61, 26))
? haystack.slice(0, -needle.length)
>haystack : Symbol(haystack, Decl(controlFlowPropertyDeclarations.ts, 61, 17))
>needle : Symbol(needle, Decl(controlFlowPropertyDeclarations.ts, 61, 26))
: haystack;
>haystack : Symbol(haystack, Decl(controlFlowPropertyDeclarations.ts, 61, 17))
}
/**
* Convert a hyphenated string to camelCase.
*/
function hyphenToCamelCase(string) {
>hyphenToCamelCase : Symbol(hyphenToCamelCase, Decl(controlFlowPropertyDeclarations.ts, 65, 1))
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 70, 27))
return string.replace(/-(.)/g, function(match, chr) {
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 70, 27))
>match : Symbol(match, Decl(controlFlowPropertyDeclarations.ts, 71, 42))
>chr : Symbol(chr, Decl(controlFlowPropertyDeclarations.ts, 71, 48))
return chr.toUpperCase();
>chr : Symbol(chr, Decl(controlFlowPropertyDeclarations.ts, 71, 48))
});
}
/**
* Determines if the specified string consists entirely of whitespace.
*/
function isEmpty(string) {
>isEmpty : Symbol(isEmpty, Decl(controlFlowPropertyDeclarations.ts, 74, 1))
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 79, 17))
return !/[^\s]/.test(string);
>/[^\s]/.test : Symbol(RegExp.test, Decl(lib.d.ts, --, --))
>test : Symbol(RegExp.test, Decl(lib.d.ts, --, --))
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 79, 17))
}
/**
* Determines if the CSS value can be converted from a
* 'px' suffixed string to a numeric value
*
* @param {string} value CSS property value
* @return {boolean}
*/
function isConvertiblePixelValue(value) {
>isConvertiblePixelValue : Symbol(isConvertiblePixelValue, Decl(controlFlowPropertyDeclarations.ts, 81, 1))
>value : Symbol(value, Decl(controlFlowPropertyDeclarations.ts, 90, 33))
return /^\d+px$/.test(value);
>/^\d+px$/.test : Symbol(RegExp.test, Decl(lib.d.ts, --, --))
>test : Symbol(RegExp.test, Decl(lib.d.ts, --, --))
>value : Symbol(value, Decl(controlFlowPropertyDeclarations.ts, 90, 33))
}
export class HTMLtoJSX {
>HTMLtoJSX : Symbol(HTMLtoJSX, Decl(controlFlowPropertyDeclarations.ts, 92, 1))
private output: string;
>output : Symbol(HTMLtoJSX.output, Decl(controlFlowPropertyDeclarations.ts, 94, 24))
private level: number;
>level : Symbol(HTMLtoJSX.level, Decl(controlFlowPropertyDeclarations.ts, 95, 27))
private _inPreTag: boolean;
>_inPreTag : Symbol(HTMLtoJSX._inPreTag, Decl(controlFlowPropertyDeclarations.ts, 96, 26))
/**
* Handles processing of the specified text node
*
* @param {TextNode} node
*/
_visitText = (node) => {
>_visitText : Symbol(HTMLtoJSX._visitText, Decl(controlFlowPropertyDeclarations.ts, 97, 31))
>node : Symbol(node, Decl(controlFlowPropertyDeclarations.ts, 105, 16))
var parentTag = node.parentNode && node.parentNode.tagName.toLowerCase();
>parentTag : Symbol(parentTag, Decl(controlFlowPropertyDeclarations.ts, 106, 7))
>node : Symbol(node, Decl(controlFlowPropertyDeclarations.ts, 105, 16))
>node : Symbol(node, Decl(controlFlowPropertyDeclarations.ts, 105, 16))
if (parentTag === 'textarea' || parentTag === 'style') {
>parentTag : Symbol(parentTag, Decl(controlFlowPropertyDeclarations.ts, 106, 7))
>parentTag : Symbol(parentTag, Decl(controlFlowPropertyDeclarations.ts, 106, 7))
// Ignore text content of textareas and styles, as it will have already been moved
// to a "defaultValue" attribute and "dangerouslySetInnerHTML" attribute respectively.
return;
}
var text = ''
>text : Symbol(text, Decl(controlFlowPropertyDeclarations.ts, 113, 7))
if (this._inPreTag) {
>this._inPreTag : Symbol(HTMLtoJSX._inPreTag, Decl(controlFlowPropertyDeclarations.ts, 96, 26))
>this : Symbol(HTMLtoJSX, Decl(controlFlowPropertyDeclarations.ts, 92, 1))
>_inPreTag : Symbol(HTMLtoJSX._inPreTag, Decl(controlFlowPropertyDeclarations.ts, 96, 26))
// If this text is contained within a <pre>, we need to ensure the JSX
// whitespace coalescing rules don't eat the whitespace. This means
// wrapping newlines and sequences of two or more spaces in variables.
text = text
>text : Symbol(text, Decl(controlFlowPropertyDeclarations.ts, 113, 7))
>text .replace(/\r/g, '') .replace : Symbol(String.replace, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>text .replace : Symbol(String.replace, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>text : Symbol(text, Decl(controlFlowPropertyDeclarations.ts, 113, 7))
.replace(/\r/g, '')
>replace : Symbol(String.replace, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
.replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) {
>replace : Symbol(String.replace, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>whitespace : Symbol(whitespace, Decl(controlFlowPropertyDeclarations.ts, 121, 50))
return '{' + JSON.stringify(whitespace) + '}';
>JSON.stringify : Symbol(JSON.stringify, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>JSON : Symbol(JSON, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>stringify : Symbol(JSON.stringify, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>whitespace : Symbol(whitespace, Decl(controlFlowPropertyDeclarations.ts, 121, 50))
});
} else {
// If there's a newline in the text, adjust the indent level
if (text.indexOf('\n') > -1) {
>text.indexOf : Symbol(String.indexOf, Decl(lib.d.ts, --, --))
>text : Symbol(text, Decl(controlFlowPropertyDeclarations.ts, 113, 7))
>indexOf : Symbol(String.indexOf, Decl(lib.d.ts, --, --))
}
}
this.output += text;
>this.output : Symbol(HTMLtoJSX.output, Decl(controlFlowPropertyDeclarations.ts, 94, 24))
>this : Symbol(HTMLtoJSX, Decl(controlFlowPropertyDeclarations.ts, 92, 1))
>output : Symbol(HTMLtoJSX.output, Decl(controlFlowPropertyDeclarations.ts, 94, 24))
>text : Symbol(text, Decl(controlFlowPropertyDeclarations.ts, 113, 7))
}
};
/**
* Handles parsing of inline styles
*/
export class StyleParser {
>StyleParser : Symbol(StyleParser, Decl(controlFlowPropertyDeclarations.ts, 134, 2))
styles = {};
>styles : Symbol(StyleParser.styles, Decl(controlFlowPropertyDeclarations.ts, 139, 26))
toJSXString = () => {
>toJSXString : Symbol(StyleParser.toJSXString, Decl(controlFlowPropertyDeclarations.ts, 140, 14))
for (var key in this.styles) {
>key : Symbol(key, Decl(controlFlowPropertyDeclarations.ts, 142, 12))
>this.styles : Symbol(StyleParser.styles, Decl(controlFlowPropertyDeclarations.ts, 139, 26))
>this : Symbol(StyleParser, Decl(controlFlowPropertyDeclarations.ts, 134, 2))
>styles : Symbol(StyleParser.styles, Decl(controlFlowPropertyDeclarations.ts, 139, 26))
if (!this.styles.hasOwnProperty(key)) {
>this.styles.hasOwnProperty : Symbol(Object.hasOwnProperty, Decl(lib.d.ts, --, --))
>this.styles : Symbol(StyleParser.styles, Decl(controlFlowPropertyDeclarations.ts, 139, 26))
>this : Symbol(StyleParser, Decl(controlFlowPropertyDeclarations.ts, 134, 2))
>styles : Symbol(StyleParser.styles, Decl(controlFlowPropertyDeclarations.ts, 139, 26))
>hasOwnProperty : Symbol(Object.hasOwnProperty, Decl(lib.d.ts, --, --))
>key : Symbol(key, Decl(controlFlowPropertyDeclarations.ts, 142, 12))
}
}
}
}

View file

@ -0,0 +1,383 @@
=== tests/cases/compiler/controlFlowPropertyDeclarations.ts ===
// Repro from ##8913
declare var require:any;
>require : any
var HTMLDOMPropertyConfig = require('react/lib/HTMLDOMPropertyConfig');
>HTMLDOMPropertyConfig : any
>require('react/lib/HTMLDOMPropertyConfig') : any
>require : any
>'react/lib/HTMLDOMPropertyConfig' : string
// Populate property map with ReactJS's attribute and property mappings
// TODO handle/use .Properties value eg: MUST_USE_PROPERTY is not HTML attr
for (var propname in HTMLDOMPropertyConfig.Properties) {
>propname : string
>HTMLDOMPropertyConfig.Properties : any
>HTMLDOMPropertyConfig : any
>Properties : any
if (!HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname)) {
>!HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname) : boolean
>HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname) : any
>HTMLDOMPropertyConfig.Properties.hasOwnProperty : any
>HTMLDOMPropertyConfig.Properties : any
>HTMLDOMPropertyConfig : any
>Properties : any
>hasOwnProperty : any
>propname : string
continue;
}
var mapFrom = HTMLDOMPropertyConfig.DOMAttributeNames[propname] || propname.toLowerCase();
>mapFrom : any
>HTMLDOMPropertyConfig.DOMAttributeNames[propname] || propname.toLowerCase() : any
>HTMLDOMPropertyConfig.DOMAttributeNames[propname] : any
>HTMLDOMPropertyConfig.DOMAttributeNames : any
>HTMLDOMPropertyConfig : any
>DOMAttributeNames : any
>propname : string
>propname.toLowerCase() : string
>propname.toLowerCase : () => string
>propname : string
>toLowerCase : () => string
}
/**
* Repeats a string a certain number of times.
* Also: the future is bright and consists of native string repetition:
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
*
* @param {string} string String to repeat
* @param {number} times Number of times to repeat string. Integer.
* @see http://jsperf.com/string-repeater/2
*/
function repeatString(string, times) {
>repeatString : (string: any, times: any) => any
>string : any
>times : any
if (times === 1) {
>times === 1 : boolean
>times : any
>1 : number
return string;
>string : any
}
if (times < 0) { throw new Error(); }
>times < 0 : boolean
>times : any
>0 : number
>new Error() : Error
>Error : ErrorConstructor
var repeated = '';
>repeated : string
>'' : string
while (times) {
>times : any
if (times & 1) {
>times & 1 : number
>times : any
>1 : number
repeated += string;
>repeated += string : string
>repeated : string
>string : any
}
if (times >>= 1) {
>times >>= 1 : number
>times : any
>1 : number
string += string;
>string += string : any
>string : any
>string : any
}
}
return repeated;
>repeated : string
}
/**
* Determine if the string ends with the specified substring.
*
* @param {string} haystack String to search in
* @param {string} needle String to search for
* @return {boolean}
*/
function endsWith(haystack, needle) {
>endsWith : (haystack: any, needle: any) => boolean
>haystack : any
>needle : any
return haystack.slice(-needle.length) === needle;
>haystack.slice(-needle.length) === needle : boolean
>haystack.slice(-needle.length) : any
>haystack.slice : any
>haystack : any
>slice : any
>-needle.length : number
>needle.length : any
>needle : any
>length : any
>needle : any
}
/**
* Trim the specified substring off the string. If the string does not end
* with the specified substring, this is a no-op.
*
* @param {string} haystack String to search in
* @param {string} needle String to search for
* @return {string}
*/
function trimEnd(haystack, needle) {
>trimEnd : (haystack: any, needle: any) => any
>haystack : any
>needle : any
return endsWith(haystack, needle)
>endsWith(haystack, needle) ? haystack.slice(0, -needle.length) : haystack : any
>endsWith(haystack, needle) : boolean
>endsWith : (haystack: any, needle: any) => boolean
>haystack : any
>needle : any
? haystack.slice(0, -needle.length)
>haystack.slice(0, -needle.length) : any
>haystack.slice : any
>haystack : any
>slice : any
>0 : number
>-needle.length : number
>needle.length : any
>needle : any
>length : any
: haystack;
>haystack : any
}
/**
* Convert a hyphenated string to camelCase.
*/
function hyphenToCamelCase(string) {
>hyphenToCamelCase : (string: any) => any
>string : any
return string.replace(/-(.)/g, function(match, chr) {
>string.replace(/-(.)/g, function(match, chr) { return chr.toUpperCase(); }) : any
>string.replace : any
>string : any
>replace : any
>/-(.)/g : RegExp
>function(match, chr) { return chr.toUpperCase(); } : (match: any, chr: any) => any
>match : any
>chr : any
return chr.toUpperCase();
>chr.toUpperCase() : any
>chr.toUpperCase : any
>chr : any
>toUpperCase : any
});
}
/**
* Determines if the specified string consists entirely of whitespace.
*/
function isEmpty(string) {
>isEmpty : (string: any) => boolean
>string : any
return !/[^\s]/.test(string);
>!/[^\s]/.test(string) : boolean
>/[^\s]/.test(string) : boolean
>/[^\s]/.test : (string: string) => boolean
>/[^\s]/ : RegExp
>test : (string: string) => boolean
>string : any
}
/**
* Determines if the CSS value can be converted from a
* 'px' suffixed string to a numeric value
*
* @param {string} value CSS property value
* @return {boolean}
*/
function isConvertiblePixelValue(value) {
>isConvertiblePixelValue : (value: any) => boolean
>value : any
return /^\d+px$/.test(value);
>/^\d+px$/.test(value) : boolean
>/^\d+px$/.test : (string: string) => boolean
>/^\d+px$/ : RegExp
>test : (string: string) => boolean
>value : any
}
export class HTMLtoJSX {
>HTMLtoJSX : HTMLtoJSX
private output: string;
>output : string
private level: number;
>level : number
private _inPreTag: boolean;
>_inPreTag : boolean
/**
* Handles processing of the specified text node
*
* @param {TextNode} node
*/
_visitText = (node) => {
>_visitText : (node: any) => void
>(node) => { var parentTag = node.parentNode && node.parentNode.tagName.toLowerCase(); if (parentTag === 'textarea' || parentTag === 'style') { // Ignore text content of textareas and styles, as it will have already been moved // to a "defaultValue" attribute and "dangerouslySetInnerHTML" attribute respectively. return; } var text = '' if (this._inPreTag) { // If this text is contained within a <pre>, we need to ensure the JSX // whitespace coalescing rules don't eat the whitespace. This means // wrapping newlines and sequences of two or more spaces in variables. text = text .replace(/\r/g, '') .replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) { return '{' + JSON.stringify(whitespace) + '}'; }); } else { // If there's a newline in the text, adjust the indent level if (text.indexOf('\n') > -1) { } } this.output += text; } : (node: any) => void
>node : any
var parentTag = node.parentNode && node.parentNode.tagName.toLowerCase();
>parentTag : any
>node.parentNode && node.parentNode.tagName.toLowerCase() : any
>node.parentNode : any
>node : any
>parentNode : any
>node.parentNode.tagName.toLowerCase() : any
>node.parentNode.tagName.toLowerCase : any
>node.parentNode.tagName : any
>node.parentNode : any
>node : any
>parentNode : any
>tagName : any
>toLowerCase : any
if (parentTag === 'textarea' || parentTag === 'style') {
>parentTag === 'textarea' || parentTag === 'style' : boolean
>parentTag === 'textarea' : boolean
>parentTag : any
>'textarea' : string
>parentTag === 'style' : boolean
>parentTag : any
>'style' : string
// Ignore text content of textareas and styles, as it will have already been moved
// to a "defaultValue" attribute and "dangerouslySetInnerHTML" attribute respectively.
return;
}
var text = ''
>text : string
>'' : string
if (this._inPreTag) {
>this._inPreTag : boolean
>this : this
>_inPreTag : boolean
// If this text is contained within a <pre>, we need to ensure the JSX
// whitespace coalescing rules don't eat the whitespace. This means
// wrapping newlines and sequences of two or more spaces in variables.
text = text
>text = text .replace(/\r/g, '') .replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) { return '{' + JSON.stringify(whitespace) + '}'; }) : string
>text : string
>text .replace(/\r/g, '') .replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) { return '{' + JSON.stringify(whitespace) + '}'; }) : string
>text .replace(/\r/g, '') .replace : { (searchValue: string, replaceValue: string): string; (searchValue: string, replacer: (substring: string, ...args: any[]) => string): string; (searchValue: RegExp, replaceValue: string): string; (searchValue: RegExp, replacer: (substring: string, ...args: any[]) => string): string; }
>text .replace(/\r/g, '') : string
>text .replace : { (searchValue: string, replaceValue: string): string; (searchValue: string, replacer: (substring: string, ...args: any[]) => string): string; (searchValue: RegExp, replaceValue: string): string; (searchValue: RegExp, replacer: (substring: string, ...args: any[]) => string): string; }
>text : string
.replace(/\r/g, '')
>replace : { (searchValue: string, replaceValue: string): string; (searchValue: string, replacer: (substring: string, ...args: any[]) => string): string; (searchValue: RegExp, replaceValue: string): string; (searchValue: RegExp, replacer: (substring: string, ...args: any[]) => string): string; }
>/\r/g : RegExp
>'' : string
.replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) {
>replace : { (searchValue: string, replaceValue: string): string; (searchValue: string, replacer: (substring: string, ...args: any[]) => string): string; (searchValue: RegExp, replaceValue: string): string; (searchValue: RegExp, replacer: (substring: string, ...args: any[]) => string): string; }
>/( {2,}|\n|\t|\{|\})/g : RegExp
>function(whitespace) { return '{' + JSON.stringify(whitespace) + '}'; } : (whitespace: string) => string
>whitespace : string
return '{' + JSON.stringify(whitespace) + '}';
>'{' + JSON.stringify(whitespace) + '}' : string
>'{' + JSON.stringify(whitespace) : string
>'{' : string
>JSON.stringify(whitespace) : string
>JSON.stringify : { (value: any, replacer?: (key: string, value: any) => any, space?: string | number): string; (value: any, replacer?: (number | string)[], space?: string | number): string; }
>JSON : JSON
>stringify : { (value: any, replacer?: (key: string, value: any) => any, space?: string | number): string; (value: any, replacer?: (number | string)[], space?: string | number): string; }
>whitespace : string
>'}' : string
});
} else {
// If there's a newline in the text, adjust the indent level
if (text.indexOf('\n') > -1) {
>text.indexOf('\n') > -1 : boolean
>text.indexOf('\n') : number
>text.indexOf : (searchString: string, position?: number) => number
>text : string
>indexOf : (searchString: string, position?: number) => number
>'\n' : string
>-1 : number
>1 : number
}
}
this.output += text;
>this.output += text : string
>this.output : string
>this : this
>output : string
>text : string
}
};
/**
* Handles parsing of inline styles
*/
export class StyleParser {
>StyleParser : StyleParser
styles = {};
>styles : {}
>{} : {}
toJSXString = () => {
>toJSXString : () => void
>() => { for (var key in this.styles) { if (!this.styles.hasOwnProperty(key)) { } } } : () => void
for (var key in this.styles) {
>key : string
>this.styles : {}
>this : this
>styles : {}
if (!this.styles.hasOwnProperty(key)) {
>!this.styles.hasOwnProperty(key) : boolean
>this.styles.hasOwnProperty(key) : boolean
>this.styles.hasOwnProperty : (v: string) => boolean
>this.styles : {}
>this : this
>styles : {}
>hasOwnProperty : (v: string) => boolean
>key : string
}
}
}
}

View file

@ -0,0 +1,148 @@
// Repro from ##8913
declare var require:any;
var HTMLDOMPropertyConfig = require('react/lib/HTMLDOMPropertyConfig');
// Populate property map with ReactJS's attribute and property mappings
// TODO handle/use .Properties value eg: MUST_USE_PROPERTY is not HTML attr
for (var propname in HTMLDOMPropertyConfig.Properties) {
if (!HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname)) {
continue;
}
var mapFrom = HTMLDOMPropertyConfig.DOMAttributeNames[propname] || propname.toLowerCase();
}
/**
* Repeats a string a certain number of times.
* Also: the future is bright and consists of native string repetition:
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
*
* @param {string} string String to repeat
* @param {number} times Number of times to repeat string. Integer.
* @see http://jsperf.com/string-repeater/2
*/
function repeatString(string, times) {
if (times === 1) {
return string;
}
if (times < 0) { throw new Error(); }
var repeated = '';
while (times) {
if (times & 1) {
repeated += string;
}
if (times >>= 1) {
string += string;
}
}
return repeated;
}
/**
* Determine if the string ends with the specified substring.
*
* @param {string} haystack String to search in
* @param {string} needle String to search for
* @return {boolean}
*/
function endsWith(haystack, needle) {
return haystack.slice(-needle.length) === needle;
}
/**
* Trim the specified substring off the string. If the string does not end
* with the specified substring, this is a no-op.
*
* @param {string} haystack String to search in
* @param {string} needle String to search for
* @return {string}
*/
function trimEnd(haystack, needle) {
return endsWith(haystack, needle)
? haystack.slice(0, -needle.length)
: haystack;
}
/**
* Convert a hyphenated string to camelCase.
*/
function hyphenToCamelCase(string) {
return string.replace(/-(.)/g, function(match, chr) {
return chr.toUpperCase();
});
}
/**
* Determines if the specified string consists entirely of whitespace.
*/
function isEmpty(string) {
return !/[^\s]/.test(string);
}
/**
* Determines if the CSS value can be converted from a
* 'px' suffixed string to a numeric value
*
* @param {string} value CSS property value
* @return {boolean}
*/
function isConvertiblePixelValue(value) {
return /^\d+px$/.test(value);
}
export class HTMLtoJSX {
private output: string;
private level: number;
private _inPreTag: boolean;
/**
* Handles processing of the specified text node
*
* @param {TextNode} node
*/
_visitText = (node) => {
var parentTag = node.parentNode && node.parentNode.tagName.toLowerCase();
if (parentTag === 'textarea' || parentTag === 'style') {
// Ignore text content of textareas and styles, as it will have already been moved
// to a "defaultValue" attribute and "dangerouslySetInnerHTML" attribute respectively.
return;
}
var text = ''
if (this._inPreTag) {
// If this text is contained within a <pre>, we need to ensure the JSX
// whitespace coalescing rules don't eat the whitespace. This means
// wrapping newlines and sequences of two or more spaces in variables.
text = text
.replace(/\r/g, '')
.replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) {
return '{' + JSON.stringify(whitespace) + '}';
});
} else {
// If there's a newline in the text, adjust the indent level
if (text.indexOf('\n') > -1) {
}
}
this.output += text;
}
};
/**
* Handles parsing of inline styles
*/
export class StyleParser {
styles = {};
toJSXString = () => {
for (var key in this.styles) {
if (!this.styles.hasOwnProperty(key)) {
}
}
}
}