diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json
index 79e31788390..c7691b06da7 100644
--- a/src/compiler/diagnosticMessages.json
+++ b/src/compiler/diagnosticMessages.json
@@ -2381,6 +2381,10 @@
"category": "Error",
"code": 5066
},
+ "Invalid value for 'jsxFactory'. '{0}' is not a valid identifier or qualified-name.": {
+ "category": "Error",
+ "code": 5067
+ },
"Concatenate and emit output to single file.": {
"category": "Message",
"code": 6001
diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts
index 92a3dcbef11..0d15a548192 100644
--- a/src/compiler/parser.ts
+++ b/src/compiler/parser.ts
@@ -438,6 +438,10 @@ namespace ts {
return result;
}
+ export function parseIsolatedEntityName(text: string, languageVersion: ScriptTarget): EntityName {
+ return Parser.parseIsolatedEntityName(text, languageVersion);
+ }
+
export function isExternalModule(file: SourceFile): boolean {
return file.externalModuleIndicator !== undefined;
}
@@ -589,6 +593,16 @@ namespace ts {
return result;
}
+ export function parseIsolatedEntityName(content: string, languageVersion: ScriptTarget): EntityName {
+ initializeState(content, languageVersion, /*syntaxCursor*/ undefined, ScriptKind.JS);
+ // Prime the scanner.
+ nextToken();
+ const entityName = parseEntityName(/*allowReservedWords*/ true);
+ const isInvalid = token() === SyntaxKind.EndOfFileToken && !parseDiagnostics.length;
+ clearState();
+ return isInvalid ? entityName : undefined;
+ }
+
function getLanguageVariant(scriptKind: ScriptKind) {
// .tsx and .jsx files are treated as jsx language variant.
return scriptKind === ScriptKind.TSX || scriptKind === ScriptKind.JSX || scriptKind === ScriptKind.JS ? LanguageVariant.JSX : LanguageVariant.Standard;
diff --git a/src/compiler/program.ts b/src/compiler/program.ts
index cb7efc49bf3..213e6a95ab1 100644
--- a/src/compiler/program.ts
+++ b/src/compiler/program.ts
@@ -1674,6 +1674,9 @@ namespace ts {
if (options.reactNamespace) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "reactNamespace", "jsxFactory"));
}
+ if (!parseIsolatedEntityName(options.jsxFactory, languageVersion)) {
+ programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Invalid_value_for_jsxFactory_0_is_not_a_valid_identifier_or_qualified_name, options.jsxFactory));
+ }
}
else if (options.reactNamespace && !isIdentifierText(options.reactNamespace, languageVersion)) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Invalid_value_for_reactNamespace_0_is_not_a_valid_identifier, options.reactNamespace));
diff --git a/src/harness/harness.ts b/src/harness/harness.ts
index a6e1ffad7f7..b227a0d8fe6 100644
--- a/src/harness/harness.ts
+++ b/src/harness/harness.ts
@@ -1768,7 +1768,7 @@ namespace Harness {
}
// Regex for parsing options in the format "@Alpha: Value of any sort"
- const optionRegex = /^[\/]{2}\s*@(\w+)\s*:\s*(\S*)/gm; // multiple matches on multiple lines
+ const optionRegex = /^[\/]{2}\s*@(\w+)\s*:\s*([^\r\n]*)/gm; // multiple matches on multiple lines
function extractCompilerSettings(content: string): CompilerSettings {
const opts: CompilerSettings = {};
@@ -1777,7 +1777,7 @@ namespace Harness {
/* tslint:disable:no-null-keyword */
while ((match = optionRegex.exec(content)) !== null) {
/* tslint:enable:no-null-keyword */
- opts[match[1]] = match[2];
+ opts[match[1]] = match[2].trim();
}
return opts;
@@ -1805,7 +1805,7 @@ namespace Harness {
// Comment line, check for global/file @options and record them
optionRegex.lastIndex = 0;
const metaDataName = testMetaData[1].toLowerCase();
- currentFileOptions[testMetaData[1]] = testMetaData[2];
+ currentFileOptions[testMetaData[1]] = testMetaData[2].trim();
if (metaDataName !== "filename") {
continue;
}
@@ -1825,12 +1825,12 @@ namespace Harness {
// Reset local data
currentFileContent = undefined;
currentFileOptions = {};
- currentFileName = testMetaData[2];
+ currentFileName = testMetaData[2].trim();
refs = [];
}
else {
// First metadata marker in the file
- currentFileName = testMetaData[2];
+ currentFileName = testMetaData[2].trim();
}
}
else {
diff --git a/tests/baselines/reference/jsxFactoryIdentifier.errors.txt b/tests/baselines/reference/jsxFactoryIdentifier.errors.txt
new file mode 100644
index 00000000000..e0cb485cf7f
--- /dev/null
+++ b/tests/baselines/reference/jsxFactoryIdentifier.errors.txt
@@ -0,0 +1,57 @@
+tests/cases/compiler/test.tsx(12,5): error TS2304: Cannot find name 'React'.
+tests/cases/compiler/test.tsx(13,5): error TS2304: Cannot find name 'React'.
+
+
+==== tests/cases/compiler/Element.ts (0 errors) ====
+
+ declare namespace JSX {
+ interface Element {
+ name: string;
+ isIntrinsic: boolean;
+ isCustomElement: boolean;
+ toString(renderId?: number): string;
+ bindDOM(renderId?: number): number;
+ resetComponent(): void;
+ instantiateComponents(renderId?: number): number;
+ props: any;
+ }
+ }
+ export namespace Element {
+ export function isElement(el: any): el is JSX.Element {
+ return el.markAsChildOfRootElement !== undefined;
+ }
+
+ export function createElement(args: any[]) {
+
+ return {
+ }
+ }
+ }
+
+ export let createElement = Element.createElement;
+
+ function toCamelCase(text: string): string {
+ return text[0].toLowerCase() + text.substring(1);
+ }
+
+==== tests/cases/compiler/test.tsx (2 errors) ====
+ import { Element} from './Element';
+ let createElement = Element.createElement;
+ let c: {
+ a?: {
+ b: string
+ }
+ };
+
+ class A {
+ view() {
+ return [
+ ,
+ ~~~~
+!!! error TS2304: Cannot find name 'React'.
+
+ ~~~~
+!!! error TS2304: Cannot find name 'React'.
+ ];
+ }
+ }
\ No newline at end of file
diff --git a/tests/baselines/reference/jsxFactoryIdentifier.js b/tests/baselines/reference/jsxFactoryIdentifier.js
new file mode 100644
index 00000000000..13abba53751
--- /dev/null
+++ b/tests/baselines/reference/jsxFactoryIdentifier.js
@@ -0,0 +1,82 @@
+//// [tests/cases/compiler/jsxFactoryIdentifier.ts] ////
+
+//// [Element.ts]
+
+declare namespace JSX {
+ interface Element {
+ name: string;
+ isIntrinsic: boolean;
+ isCustomElement: boolean;
+ toString(renderId?: number): string;
+ bindDOM(renderId?: number): number;
+ resetComponent(): void;
+ instantiateComponents(renderId?: number): number;
+ props: any;
+ }
+}
+export namespace Element {
+ export function isElement(el: any): el is JSX.Element {
+ return el.markAsChildOfRootElement !== undefined;
+ }
+
+ export function createElement(args: any[]) {
+
+ return {
+ }
+ }
+}
+
+export let createElement = Element.createElement;
+
+function toCamelCase(text: string): string {
+ return text[0].toLowerCase() + text.substring(1);
+}
+
+//// [test.tsx]
+import { Element} from './Element';
+let createElement = Element.createElement;
+let c: {
+ a?: {
+ b: string
+ }
+};
+
+class A {
+ view() {
+ return [
+ ,
+
+ ];
+ }
+}
+
+//// [Element.js]
+"use strict";
+var Element;
+(function (Element) {
+ function isElement(el) {
+ return el.markAsChildOfRootElement !== undefined;
+ }
+ Element.isElement = isElement;
+ function createElement(args) {
+ return {};
+ }
+ Element.createElement = createElement;
+})(Element = exports.Element || (exports.Element = {}));
+exports.createElement = Element.createElement;
+function toCamelCase(text) {
+ return text[0].toLowerCase() + text.substring(1);
+}
+//// [test.js]
+"use strict";
+const Element_1 = require("./Element");
+let createElement = Element_1.Element.createElement;
+let c;
+class A {
+ view() {
+ return [
+ React.createElement("meta", { content: "helloworld" }),
+ React.createElement("meta", { content: c.a.b })
+ ];
+ }
+}
diff --git a/tests/baselines/reference/jsxFactoryNotIdentifierOrQualifiedName.errors.txt b/tests/baselines/reference/jsxFactoryNotIdentifierOrQualifiedName.errors.txt
new file mode 100644
index 00000000000..e14f5f988f8
--- /dev/null
+++ b/tests/baselines/reference/jsxFactoryNotIdentifierOrQualifiedName.errors.txt
@@ -0,0 +1,59 @@
+error TS5067: Invalid value for 'jsxFactory'. 'Element.createElement=' is not a valid identifier or qualified-name.
+tests/cases/compiler/test.tsx(12,5): error TS2304: Cannot find name 'React'.
+tests/cases/compiler/test.tsx(13,5): error TS2304: Cannot find name 'React'.
+
+
+!!! error TS5067: Invalid value for 'jsxFactory'. 'Element.createElement=' is not a valid identifier or qualified-name.
+==== tests/cases/compiler/Element.ts (0 errors) ====
+
+ declare namespace JSX {
+ interface Element {
+ name: string;
+ isIntrinsic: boolean;
+ isCustomElement: boolean;
+ toString(renderId?: number): string;
+ bindDOM(renderId?: number): number;
+ resetComponent(): void;
+ instantiateComponents(renderId?: number): number;
+ props: any;
+ }
+ }
+ export namespace Element {
+ export function isElement(el: any): el is JSX.Element {
+ return el.markAsChildOfRootElement !== undefined;
+ }
+
+ export function createElement(args: any[]) {
+
+ return {
+ }
+ }
+ }
+
+ export let createElement = Element.createElement;
+
+ function toCamelCase(text: string): string {
+ return text[0].toLowerCase() + text.substring(1);
+ }
+
+==== tests/cases/compiler/test.tsx (2 errors) ====
+ import { Element} from './Element';
+
+ let c: {
+ a?: {
+ b: string
+ }
+ };
+
+ class A {
+ view() {
+ return [
+ ,
+ ~~~~
+!!! error TS2304: Cannot find name 'React'.
+
+ ~~~~
+!!! error TS2304: Cannot find name 'React'.
+ ];
+ }
+ }
\ No newline at end of file
diff --git a/tests/baselines/reference/jsxFactoryNotIdentifierOrQualifiedName.js b/tests/baselines/reference/jsxFactoryNotIdentifierOrQualifiedName.js
new file mode 100644
index 00000000000..90bb675442a
--- /dev/null
+++ b/tests/baselines/reference/jsxFactoryNotIdentifierOrQualifiedName.js
@@ -0,0 +1,80 @@
+//// [tests/cases/compiler/jsxFactoryNotIdentifierOrQualifiedName.ts] ////
+
+//// [Element.ts]
+
+declare namespace JSX {
+ interface Element {
+ name: string;
+ isIntrinsic: boolean;
+ isCustomElement: boolean;
+ toString(renderId?: number): string;
+ bindDOM(renderId?: number): number;
+ resetComponent(): void;
+ instantiateComponents(renderId?: number): number;
+ props: any;
+ }
+}
+export namespace Element {
+ export function isElement(el: any): el is JSX.Element {
+ return el.markAsChildOfRootElement !== undefined;
+ }
+
+ export function createElement(args: any[]) {
+
+ return {
+ }
+ }
+}
+
+export let createElement = Element.createElement;
+
+function toCamelCase(text: string): string {
+ return text[0].toLowerCase() + text.substring(1);
+}
+
+//// [test.tsx]
+import { Element} from './Element';
+
+let c: {
+ a?: {
+ b: string
+ }
+};
+
+class A {
+ view() {
+ return [
+ ,
+
+ ];
+ }
+}
+
+//// [Element.js]
+"use strict";
+var Element;
+(function (Element) {
+ function isElement(el) {
+ return el.markAsChildOfRootElement !== undefined;
+ }
+ Element.isElement = isElement;
+ function createElement(args) {
+ return {};
+ }
+ Element.createElement = createElement;
+})(Element = exports.Element || (exports.Element = {}));
+exports.createElement = Element.createElement;
+function toCamelCase(text) {
+ return text[0].toLowerCase() + text.substring(1);
+}
+//// [test.js]
+"use strict";
+let c;
+class A {
+ view() {
+ return [
+ React.createElement("meta", { content: "helloworld" }),
+ React.createElement("meta", { content: c.a.b })
+ ];
+ }
+}
diff --git a/tests/baselines/reference/jsxFactoryNotIdentifierOrQualifiedName2.errors.txt b/tests/baselines/reference/jsxFactoryNotIdentifierOrQualifiedName2.errors.txt
new file mode 100644
index 00000000000..1c33f3a7a51
--- /dev/null
+++ b/tests/baselines/reference/jsxFactoryNotIdentifierOrQualifiedName2.errors.txt
@@ -0,0 +1,59 @@
+error TS5067: Invalid value for 'jsxFactory'. 'id1 id2' is not a valid identifier or qualified-name.
+tests/cases/compiler/test.tsx(12,5): error TS2304: Cannot find name 'React'.
+tests/cases/compiler/test.tsx(13,5): error TS2304: Cannot find name 'React'.
+
+
+!!! error TS5067: Invalid value for 'jsxFactory'. 'id1 id2' is not a valid identifier or qualified-name.
+==== tests/cases/compiler/Element.ts (0 errors) ====
+
+ declare namespace JSX {
+ interface Element {
+ name: string;
+ isIntrinsic: boolean;
+ isCustomElement: boolean;
+ toString(renderId?: number): string;
+ bindDOM(renderId?: number): number;
+ resetComponent(): void;
+ instantiateComponents(renderId?: number): number;
+ props: any;
+ }
+ }
+ export namespace Element {
+ export function isElement(el: any): el is JSX.Element {
+ return el.markAsChildOfRootElement !== undefined;
+ }
+
+ export function createElement(args: any[]) {
+
+ return {
+ }
+ }
+ }
+
+ export let createElement = Element.createElement;
+
+ function toCamelCase(text: string): string {
+ return text[0].toLowerCase() + text.substring(1);
+ }
+
+==== tests/cases/compiler/test.tsx (2 errors) ====
+ import { Element} from './Element';
+
+ let c: {
+ a?: {
+ b: string
+ }
+ };
+
+ class A {
+ view() {
+ return [
+ ,
+ ~~~~
+!!! error TS2304: Cannot find name 'React'.
+
+ ~~~~
+!!! error TS2304: Cannot find name 'React'.
+ ];
+ }
+ }
\ No newline at end of file
diff --git a/tests/baselines/reference/jsxFactoryNotIdentifierOrQualifiedName2.js b/tests/baselines/reference/jsxFactoryNotIdentifierOrQualifiedName2.js
new file mode 100644
index 00000000000..0bc0c6e57c5
--- /dev/null
+++ b/tests/baselines/reference/jsxFactoryNotIdentifierOrQualifiedName2.js
@@ -0,0 +1,80 @@
+//// [tests/cases/compiler/jsxFactoryNotIdentifierOrQualifiedName2.ts] ////
+
+//// [Element.ts]
+
+declare namespace JSX {
+ interface Element {
+ name: string;
+ isIntrinsic: boolean;
+ isCustomElement: boolean;
+ toString(renderId?: number): string;
+ bindDOM(renderId?: number): number;
+ resetComponent(): void;
+ instantiateComponents(renderId?: number): number;
+ props: any;
+ }
+}
+export namespace Element {
+ export function isElement(el: any): el is JSX.Element {
+ return el.markAsChildOfRootElement !== undefined;
+ }
+
+ export function createElement(args: any[]) {
+
+ return {
+ }
+ }
+}
+
+export let createElement = Element.createElement;
+
+function toCamelCase(text: string): string {
+ return text[0].toLowerCase() + text.substring(1);
+}
+
+//// [test.tsx]
+import { Element} from './Element';
+
+let c: {
+ a?: {
+ b: string
+ }
+};
+
+class A {
+ view() {
+ return [
+ ,
+
+ ];
+ }
+}
+
+//// [Element.js]
+"use strict";
+var Element;
+(function (Element) {
+ function isElement(el) {
+ return el.markAsChildOfRootElement !== undefined;
+ }
+ Element.isElement = isElement;
+ function createElement(args) {
+ return {};
+ }
+ Element.createElement = createElement;
+})(Element = exports.Element || (exports.Element = {}));
+exports.createElement = Element.createElement;
+function toCamelCase(text) {
+ return text[0].toLowerCase() + text.substring(1);
+}
+//// [test.js]
+"use strict";
+let c;
+class A {
+ view() {
+ return [
+ React.createElement("meta", { content: "helloworld" }),
+ React.createElement("meta", { content: c.a.b })
+ ];
+ }
+}
diff --git a/tests/baselines/reference/jsxFactoryQualifiedName.errors.txt b/tests/baselines/reference/jsxFactoryQualifiedName.errors.txt
new file mode 100644
index 00000000000..32c8500ea3b
--- /dev/null
+++ b/tests/baselines/reference/jsxFactoryQualifiedName.errors.txt
@@ -0,0 +1,57 @@
+tests/cases/compiler/test.tsx(12,5): error TS2304: Cannot find name 'React'.
+tests/cases/compiler/test.tsx(13,5): error TS2304: Cannot find name 'React'.
+
+
+==== tests/cases/compiler/Element.ts (0 errors) ====
+
+ declare namespace JSX {
+ interface Element {
+ name: string;
+ isIntrinsic: boolean;
+ isCustomElement: boolean;
+ toString(renderId?: number): string;
+ bindDOM(renderId?: number): number;
+ resetComponent(): void;
+ instantiateComponents(renderId?: number): number;
+ props: any;
+ }
+ }
+ export namespace Element {
+ export function isElement(el: any): el is JSX.Element {
+ return el.markAsChildOfRootElement !== undefined;
+ }
+
+ export function createElement(args: any[]) {
+
+ return {
+ }
+ }
+ }
+
+ export let createElement = Element.createElement;
+
+ function toCamelCase(text: string): string {
+ return text[0].toLowerCase() + text.substring(1);
+ }
+
+==== tests/cases/compiler/test.tsx (2 errors) ====
+ import { Element} from './Element';
+
+ let c: {
+ a?: {
+ b: string
+ }
+ };
+
+ class A {
+ view() {
+ return [
+ ,
+ ~~~~
+!!! error TS2304: Cannot find name 'React'.
+
+ ~~~~
+!!! error TS2304: Cannot find name 'React'.
+ ];
+ }
+ }
\ No newline at end of file
diff --git a/tests/baselines/reference/jsxFactoryQualifiedName.js b/tests/baselines/reference/jsxFactoryQualifiedName.js
new file mode 100644
index 00000000000..aec6614bf01
--- /dev/null
+++ b/tests/baselines/reference/jsxFactoryQualifiedName.js
@@ -0,0 +1,80 @@
+//// [tests/cases/compiler/jsxFactoryQualifiedName.ts] ////
+
+//// [Element.ts]
+
+declare namespace JSX {
+ interface Element {
+ name: string;
+ isIntrinsic: boolean;
+ isCustomElement: boolean;
+ toString(renderId?: number): string;
+ bindDOM(renderId?: number): number;
+ resetComponent(): void;
+ instantiateComponents(renderId?: number): number;
+ props: any;
+ }
+}
+export namespace Element {
+ export function isElement(el: any): el is JSX.Element {
+ return el.markAsChildOfRootElement !== undefined;
+ }
+
+ export function createElement(args: any[]) {
+
+ return {
+ }
+ }
+}
+
+export let createElement = Element.createElement;
+
+function toCamelCase(text: string): string {
+ return text[0].toLowerCase() + text.substring(1);
+}
+
+//// [test.tsx]
+import { Element} from './Element';
+
+let c: {
+ a?: {
+ b: string
+ }
+};
+
+class A {
+ view() {
+ return [
+ ,
+
+ ];
+ }
+}
+
+//// [Element.js]
+"use strict";
+var Element;
+(function (Element) {
+ function isElement(el) {
+ return el.markAsChildOfRootElement !== undefined;
+ }
+ Element.isElement = isElement;
+ function createElement(args) {
+ return {};
+ }
+ Element.createElement = createElement;
+})(Element = exports.Element || (exports.Element = {}));
+exports.createElement = Element.createElement;
+function toCamelCase(text) {
+ return text[0].toLowerCase() + text.substring(1);
+}
+//// [test.js]
+"use strict";
+let c;
+class A {
+ view() {
+ return [
+ React.createElement("meta", { content: "helloworld" }),
+ React.createElement("meta", { content: c.a.b })
+ ];
+ }
+}
diff --git a/tests/cases/compiler/jsxFactoryIdentifier.ts b/tests/cases/compiler/jsxFactoryIdentifier.ts
new file mode 100644
index 00000000000..9531abeeebf
--- /dev/null
+++ b/tests/cases/compiler/jsxFactoryIdentifier.ts
@@ -0,0 +1,53 @@
+//@jsx: react
+//@target: es6
+//@module: commonjs
+//@jsxFactory: createElement
+
+// @filename: Element.ts
+declare namespace JSX {
+ interface Element {
+ name: string;
+ isIntrinsic: boolean;
+ isCustomElement: boolean;
+ toString(renderId?: number): string;
+ bindDOM(renderId?: number): number;
+ resetComponent(): void;
+ instantiateComponents(renderId?: number): number;
+ props: any;
+ }
+}
+export namespace Element {
+ export function isElement(el: any): el is JSX.Element {
+ return el.markAsChildOfRootElement !== undefined;
+ }
+
+ export function createElement(args: any[]) {
+
+ return {
+ }
+ }
+}
+
+export let createElement = Element.createElement;
+
+function toCamelCase(text: string): string {
+ return text[0].toLowerCase() + text.substring(1);
+}
+
+// @filename: test.tsx
+import { Element} from './Element';
+let createElement = Element.createElement;
+let c: {
+ a?: {
+ b: string
+ }
+};
+
+class A {
+ view() {
+ return [
+ ,
+
+ ];
+ }
+}
\ No newline at end of file
diff --git a/tests/cases/compiler/jsxFactoryNotIdentifierOrQualifiedName.ts b/tests/cases/compiler/jsxFactoryNotIdentifierOrQualifiedName.ts
new file mode 100644
index 00000000000..6f7c584d232
--- /dev/null
+++ b/tests/cases/compiler/jsxFactoryNotIdentifierOrQualifiedName.ts
@@ -0,0 +1,53 @@
+//@jsx: react
+//@target: es6
+//@module: commonjs
+//@jsxFactory: Element.createElement=
+
+// @filename: Element.ts
+declare namespace JSX {
+ interface Element {
+ name: string;
+ isIntrinsic: boolean;
+ isCustomElement: boolean;
+ toString(renderId?: number): string;
+ bindDOM(renderId?: number): number;
+ resetComponent(): void;
+ instantiateComponents(renderId?: number): number;
+ props: any;
+ }
+}
+export namespace Element {
+ export function isElement(el: any): el is JSX.Element {
+ return el.markAsChildOfRootElement !== undefined;
+ }
+
+ export function createElement(args: any[]) {
+
+ return {
+ }
+ }
+}
+
+export let createElement = Element.createElement;
+
+function toCamelCase(text: string): string {
+ return text[0].toLowerCase() + text.substring(1);
+}
+
+// @filename: test.tsx
+import { Element} from './Element';
+
+let c: {
+ a?: {
+ b: string
+ }
+};
+
+class A {
+ view() {
+ return [
+ ,
+
+ ];
+ }
+}
\ No newline at end of file
diff --git a/tests/cases/compiler/jsxFactoryNotIdentifierOrQualifiedName2.ts b/tests/cases/compiler/jsxFactoryNotIdentifierOrQualifiedName2.ts
new file mode 100644
index 00000000000..610063f7d34
--- /dev/null
+++ b/tests/cases/compiler/jsxFactoryNotIdentifierOrQualifiedName2.ts
@@ -0,0 +1,53 @@
+//@jsx: react
+//@target: es6
+//@module: commonjs
+//@jsxFactory: id1 id2
+
+// @filename: Element.ts
+declare namespace JSX {
+ interface Element {
+ name: string;
+ isIntrinsic: boolean;
+ isCustomElement: boolean;
+ toString(renderId?: number): string;
+ bindDOM(renderId?: number): number;
+ resetComponent(): void;
+ instantiateComponents(renderId?: number): number;
+ props: any;
+ }
+}
+export namespace Element {
+ export function isElement(el: any): el is JSX.Element {
+ return el.markAsChildOfRootElement !== undefined;
+ }
+
+ export function createElement(args: any[]) {
+
+ return {
+ }
+ }
+}
+
+export let createElement = Element.createElement;
+
+function toCamelCase(text: string): string {
+ return text[0].toLowerCase() + text.substring(1);
+}
+
+// @filename: test.tsx
+import { Element} from './Element';
+
+let c: {
+ a?: {
+ b: string
+ }
+};
+
+class A {
+ view() {
+ return [
+ ,
+
+ ];
+ }
+}
\ No newline at end of file
diff --git a/tests/cases/compiler/jsxFactoryQualifiedName.ts b/tests/cases/compiler/jsxFactoryQualifiedName.ts
new file mode 100644
index 00000000000..c8d9317138b
--- /dev/null
+++ b/tests/cases/compiler/jsxFactoryQualifiedName.ts
@@ -0,0 +1,53 @@
+//@jsx: react
+//@target: es6
+//@module: commonjs
+//@jsxFactory: Element.createElement
+
+// @filename: Element.ts
+declare namespace JSX {
+ interface Element {
+ name: string;
+ isIntrinsic: boolean;
+ isCustomElement: boolean;
+ toString(renderId?: number): string;
+ bindDOM(renderId?: number): number;
+ resetComponent(): void;
+ instantiateComponents(renderId?: number): number;
+ props: any;
+ }
+}
+export namespace Element {
+ export function isElement(el: any): el is JSX.Element {
+ return el.markAsChildOfRootElement !== undefined;
+ }
+
+ export function createElement(args: any[]) {
+
+ return {
+ }
+ }
+}
+
+export let createElement = Element.createElement;
+
+function toCamelCase(text: string): string {
+ return text[0].toLowerCase() + text.substring(1);
+}
+
+// @filename: test.tsx
+import { Element} from './Element';
+
+let c: {
+ a?: {
+ b: string
+ }
+};
+
+class A {
+ view() {
+ return [
+ ,
+
+ ];
+ }
+}
\ No newline at end of file