Verify that jsxFactory is either identifier or qualified name

This commit is contained in:
Sheetal Nandi 2016-11-09 13:15:13 -08:00
parent 4b8a55793a
commit f7bac98948
16 changed files with 792 additions and 5 deletions

View File

@ -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

View File

@ -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;

View File

@ -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));

View File

@ -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 {

View File

@ -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 [
<meta content="helloworld"></meta>,
~~~~
!!! error TS2304: Cannot find name 'React'.
<meta content={c.a!.b}></meta>
~~~~
!!! error TS2304: Cannot find name 'React'.
];
}
}

View File

@ -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 [
<meta content="helloworld"></meta>,
<meta content={c.a!.b}></meta>
];
}
}
//// [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 })
];
}
}

View File

@ -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 [
<meta content="helloworld"></meta>,
~~~~
!!! error TS2304: Cannot find name 'React'.
<meta content={c.a!.b}></meta>
~~~~
!!! error TS2304: Cannot find name 'React'.
];
}
}

View File

@ -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 [
<meta content="helloworld"></meta>,
<meta content={c.a!.b}></meta>
];
}
}
//// [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 })
];
}
}

View File

@ -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 [
<meta content="helloworld"></meta>,
~~~~
!!! error TS2304: Cannot find name 'React'.
<meta content={c.a!.b}></meta>
~~~~
!!! error TS2304: Cannot find name 'React'.
];
}
}

View File

@ -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 [
<meta content="helloworld"></meta>,
<meta content={c.a!.b}></meta>
];
}
}
//// [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 })
];
}
}

View File

@ -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 [
<meta content="helloworld"></meta>,
~~~~
!!! error TS2304: Cannot find name 'React'.
<meta content={c.a!.b}></meta>
~~~~
!!! error TS2304: Cannot find name 'React'.
];
}
}

View File

@ -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 [
<meta content="helloworld"></meta>,
<meta content={c.a!.b}></meta>
];
}
}
//// [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 })
];
}
}

View File

@ -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 [
<meta content="helloworld"></meta>,
<meta content={c.a!.b}></meta>
];
}
}

View File

@ -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 [
<meta content="helloworld"></meta>,
<meta content={c.a!.b}></meta>
];
}
}

View File

@ -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 [
<meta content="helloworld"></meta>,
<meta content={c.a!.b}></meta>
];
}
}

View File

@ -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 [
<meta content="helloworld"></meta>,
<meta content={c.a!.b}></meta>
];
}
}