Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support xml namespace prefix for JSX elements and attributes #37421

Merged
merged 9 commits into from
Nov 2, 2020
4 changes: 0 additions & 4 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24574,11 +24574,7 @@ namespace ts {
return getJsxElementTypeAt(node) || anyType;
}

/**
* Returns true iff the JSX element name would be a valid JS identifier, ignoring restrictions about keywords not being identifiers
*/
function isUnhyphenatedJsxName(name: string | __String) {
// - is the only character supported in JSX attribute names that isn't valid in JavaScript identifiers
return !stringContains(name as string, "-");
}

Expand Down
15 changes: 14 additions & 1 deletion src/compiler/scanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2305,22 +2305,35 @@ namespace ts {
// they allow dashes
function scanJsxIdentifier(): SyntaxKind {
if (tokenIsIdentifierOrKeyword(token)) {
// An identifier or keyword has already been parsed - check for a `-` and then append it and everything after it to the token
// An identifier or keyword has already been parsed - check for a `-` or a single instance of `:` and then append it and
// everything after it to the token
// Do note that this means that `scanJsxIdentifier` effectively _mutates_ the visible token without advancing to a new token
// Any caller should be expecting this behavior and should only read the pos or token value after calling it.
let namespaceSeparator = false;
while (pos < end) {
const ch = text.charCodeAt(pos);
if (ch === CharacterCodes.minus) {
tokenValue += "-";
pos++;
continue;
}
else if (ch === CharacterCodes.colon && !namespaceSeparator) {
tokenValue += ":";
pos++;
namespaceSeparator = true;
continue;
}
const oldPos = pos;
tokenValue += scanIdentifierParts(); // reuse `scanIdentifierParts` so unicode escapes are handled
if (pos === oldPos) {
break;
}
}
// Do not include a trailing namespace separator in the token, since this is against the spec.
if (tokenValue.slice(-1) === ":") {
tokenValue = tokenValue.slice(0, -1);
pos--;
}
}
return token;
}
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3810,7 +3810,7 @@ namespace ts {

export function isIntrinsicJsxName(name: __String | string) {
const ch = (name as string).charCodeAt(0);
return (ch >= CharacterCodes.a && ch <= CharacterCodes.z) || stringContains((name as string), "-");
return (ch >= CharacterCodes.a && ch <= CharacterCodes.z) || stringContains((name as string), "-") || stringContains((name as string), ":");
}

const indentStrings: string[] = ["", " "];
Expand Down
19 changes: 10 additions & 9 deletions tests/baselines/reference/jsxEsprimaFbTestSuite.errors.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(39,1): error TS2657: JSX expressions must have one parent element.
tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(39,17): error TS1005: '{' expected.
tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(39,23): error TS1005: ';' expected.
tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(39,23): error TS2304: Cannot find name 'right'.
tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(39,41): error TS1382: Unexpected token. Did you mean `{'>'}` or `&gt;`?
tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(39,57): error TS1109: Expression expected.
tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(39,58): error TS1109: Expression expected.
tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(40,1): error TS2657: JSX expressions must have one parent element.
tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(40,17): error TS1005: '{' expected.
tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(40,23): error TS1005: ';' expected.
tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(40,23): error TS2304: Cannot find name 'right'.
tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(40,41): error TS1382: Unexpected token. Did you mean `{'>'}` or `&gt;`?
tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(40,57): error TS1109: Expression expected.
tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(40,58): error TS1109: Expression expected.


==== tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx (7 errors) ====
Expand All @@ -15,12 +15,13 @@ tests/cases/conformance/jsx/jsxEsprimaFbTestSuite.tsx(39,58): error TS1109: Expr
declare var x;
declare var a;
declare var props;
declare var value;

<a />;

//<n:a n:v />; Namespace unsuported
<n:a n:v />;

//<a n:foo="bar"> {value} <b><c /></b></a>; Namespace unsuported
<a n:foo="bar"> {value} <b><c /></b></a>;

<a b={" "} c=" " d="&amp;" e="id=1&group=2" f="&#123456789" g="&#123*;" h="&#x;" />;

Expand Down
9 changes: 5 additions & 4 deletions tests/baselines/reference/jsxEsprimaFbTestSuite.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ declare var LeftRight;
declare var x;
declare var a;
declare var props;
declare var value;

<a />;

//<n:a n:v />; Namespace unsuported
<n:a n:v />;

//<a n:foo="bar"> {value} <b><c /></b></a>; Namespace unsuported
<a n:foo="bar"> {value} <b><c /></b></a>;

<a b={" "} c=" " d="&amp;" e="id=1&group=2" f="&#123456789" g="&#123*;" h="&#x;" />;

Expand Down Expand Up @@ -56,8 +57,8 @@ baz

//// [jsxEsprimaFbTestSuite.jsx]
<a />;
//<n:a n:v />; Namespace unsuported
//<a n:foo="bar"> {value} <b><c /></b></a>; Namespace unsuported
<n:a n:v/>;
<a n:foo="bar"> {value} <b><c /></b></a>;
<a b={" "} c=" " d="&amp;" e="id=1&group=2" f="&#123456789" g="&#123*;" h="&#x;"/>;
<a b="&notanentity;"/>;
<a />;
Expand Down
38 changes: 22 additions & 16 deletions tests/baselines/reference/jsxEsprimaFbTestSuite.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,29 @@ declare var a;
declare var props;
>props : Symbol(props, Decl(jsxEsprimaFbTestSuite.tsx, 6, 11))

declare var value;
>value : Symbol(value, Decl(jsxEsprimaFbTestSuite.tsx, 7, 11))

<a />;

//<n:a n:v />; Namespace unsuported
<n:a n:v />;
>n:v : Symbol(n:v, Decl(jsxEsprimaFbTestSuite.tsx, 11, 4))

//<a n:foo="bar"> {value} <b><c /></b></a>; Namespace unsuported
<a n:foo="bar"> {value} <b><c /></b></a>;
>n:foo : Symbol(n:foo, Decl(jsxEsprimaFbTestSuite.tsx, 13, 2))
>value : Symbol(value, Decl(jsxEsprimaFbTestSuite.tsx, 7, 11))

<a b={" "} c=" " d="&amp;" e="id=1&group=2" f="&#123456789" g="&#123*;" h="&#x;" />;
>b : Symbol(b, Decl(jsxEsprimaFbTestSuite.tsx, 14, 2))
>c : Symbol(c, Decl(jsxEsprimaFbTestSuite.tsx, 14, 10))
>d : Symbol(d, Decl(jsxEsprimaFbTestSuite.tsx, 14, 16))
>e : Symbol(e, Decl(jsxEsprimaFbTestSuite.tsx, 14, 26))
>f : Symbol(f, Decl(jsxEsprimaFbTestSuite.tsx, 14, 43))
>g : Symbol(g, Decl(jsxEsprimaFbTestSuite.tsx, 14, 59))
>h : Symbol(h, Decl(jsxEsprimaFbTestSuite.tsx, 14, 71))
>b : Symbol(b, Decl(jsxEsprimaFbTestSuite.tsx, 15, 2))
>c : Symbol(c, Decl(jsxEsprimaFbTestSuite.tsx, 15, 10))
>d : Symbol(d, Decl(jsxEsprimaFbTestSuite.tsx, 15, 16))
>e : Symbol(e, Decl(jsxEsprimaFbTestSuite.tsx, 15, 26))
>f : Symbol(f, Decl(jsxEsprimaFbTestSuite.tsx, 15, 43))
>g : Symbol(g, Decl(jsxEsprimaFbTestSuite.tsx, 15, 59))
>h : Symbol(h, Decl(jsxEsprimaFbTestSuite.tsx, 15, 71))

<a b="&notanentity;" />;
>b : Symbol(b, Decl(jsxEsprimaFbTestSuite.tsx, 16, 2))
>b : Symbol(b, Decl(jsxEsprimaFbTestSuite.tsx, 17, 2))

<a
/>;
Expand All @@ -49,15 +55,15 @@ declare var props;
>AbC_def : Symbol(AbC_def, Decl(jsxEsprimaFbTestSuite.tsx, 2, 11))

test="&#x0026;&#38;">
>test : Symbol(test, Decl(jsxEsprimaFbTestSuite.tsx, 22, 8))
>test : Symbol(test, Decl(jsxEsprimaFbTestSuite.tsx, 23, 8))

bar
baz
</AbC_def>;
>AbC_def : Symbol(AbC_def, Decl(jsxEsprimaFbTestSuite.tsx, 2, 11))

<a b={x ? <c /> : <d />} />;
>b : Symbol(b, Decl(jsxEsprimaFbTestSuite.tsx, 28, 2))
>b : Symbol(b, Decl(jsxEsprimaFbTestSuite.tsx, 29, 2))
>x : Symbol(x, Decl(jsxEsprimaFbTestSuite.tsx, 4, 11))

<a>{}</a>;
Expand All @@ -70,7 +76,7 @@ baz

<LeftRight left=<a /> right=<b>monkeys /> gorillas</b> />;
>LeftRight : Symbol(LeftRight, Decl(jsxEsprimaFbTestSuite.tsx, 3, 11))
>left : Symbol(left, Decl(jsxEsprimaFbTestSuite.tsx, 38, 10))
>left : Symbol(left, Decl(jsxEsprimaFbTestSuite.tsx, 39, 10))

<a.b></a.b>;
>a : Symbol(a, Decl(jsxEsprimaFbTestSuite.tsx, 5, 11))
Expand All @@ -88,11 +94,11 @@ baz

<div {...props} post="attribute" />;
>props : Symbol(props, Decl(jsxEsprimaFbTestSuite.tsx, 6, 11))
>post : Symbol(post, Decl(jsxEsprimaFbTestSuite.tsx, 48, 15))
>post : Symbol(post, Decl(jsxEsprimaFbTestSuite.tsx, 49, 15))

<div pre="leading" pre2="attribute" {...props}></div>;
>pre : Symbol(pre, Decl(jsxEsprimaFbTestSuite.tsx, 50, 4))
>pre2 : Symbol(pre2, Decl(jsxEsprimaFbTestSuite.tsx, 50, 18))
>pre : Symbol(pre, Decl(jsxEsprimaFbTestSuite.tsx, 51, 4))
>pre2 : Symbol(pre2, Decl(jsxEsprimaFbTestSuite.tsx, 51, 18))
>props : Symbol(props, Decl(jsxEsprimaFbTestSuite.tsx, 6, 11))

<a> </a>;
Expand Down
20 changes: 18 additions & 2 deletions tests/baselines/reference/jsxEsprimaFbTestSuite.types
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,29 @@ declare var a;
declare var props;
>props : any

declare var value;
>value : any

<a />;
><a /> : any
>a : any

//<n:a n:v />; Namespace unsuported
<n:a n:v />;
><n:a n:v /> : any
>n:a : any
>n:v : true

//<a n:foo="bar"> {value} <b><c /></b></a>; Namespace unsuported
<a n:foo="bar"> {value} <b><c /></b></a>;
><a n:foo="bar"> {value} <b><c /></b></a> : any
>a : any
>n:foo : string
>value : any
><b><c /></b> : any
>b : any
><c /> : any
>c : any
>b : any
>a : any

<a b={" "} c=" " d="&amp;" e="id=1&group=2" f="&#123456789" g="&#123*;" h="&#x;" />;
><a b={" "} c=" " d="&amp;" e="id=1&group=2" f="&#123456789" g="&#123*;" h="&#x;" /> : any
Expand Down
32 changes: 10 additions & 22 deletions tests/baselines/reference/jsxInvalidEsprimaTestSuite.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,9 @@ tests/cases/conformance/jsx/5.tsx(1,2): error TS17008: JSX element 'a' has no co
tests/cases/conformance/jsx/5.tsx(1,5): error TS1005: '</' expected.
tests/cases/conformance/jsx/6.tsx(1,4): error TS17002: Expected corresponding JSX closing tag for 'a'.
tests/cases/conformance/jsx/7.tsx(1,13): error TS1002: Unterminated string literal.
tests/cases/conformance/jsx/8.tsx(1,3): error TS1003: Identifier expected.
tests/cases/conformance/jsx/8.tsx(1,6): error TS17002: Expected corresponding JSX closing tag for 'a'.
tests/cases/conformance/jsx/9.tsx(1,3): error TS1003: Identifier expected.
tests/cases/conformance/jsx/9.tsx(1,5): error TS1003: Identifier expected.
tests/cases/conformance/jsx/9.tsx(1,11): error TS1005: '>' expected.
tests/cases/conformance/jsx/9.tsx(1,12): error TS2304: Cannot find name 'b'.
tests/cases/conformance/jsx/9.tsx(1,16): error TS1109: Expression expected.
tests/cases/conformance/jsx/8.tsx(1,6): error TS17002: Expected corresponding JSX closing tag for 'a:b'.
tests/cases/conformance/jsx/9.tsx(1,2): error TS2304: Cannot find name 'a:b'.
tests/cases/conformance/jsx/9.tsx(1,10): error TS2304: Cannot find name 'a:b'.


==== tests/cases/conformance/jsx/1.tsx (3 errors) ====
Expand Down Expand Up @@ -128,24 +124,16 @@ tests/cases/conformance/jsx/9.tsx(1,16): error TS1109: Expression expected.
<a foo="bar;

!!! error TS1002: Unterminated string literal.
==== tests/cases/conformance/jsx/8.tsx (2 errors) ====
==== tests/cases/conformance/jsx/8.tsx (1 errors) ====
<a:b></b>;
~
!!! error TS1003: Identifier expected.
~~~~
!!! error TS17002: Expected corresponding JSX closing tag for 'a'.
==== tests/cases/conformance/jsx/9.tsx (5 errors) ====
!!! error TS17002: Expected corresponding JSX closing tag for 'a:b'.
==== tests/cases/conformance/jsx/9.tsx (2 errors) ====
<a:b.c></a:b.c>;
~
!!! error TS1003: Identifier expected.
~
!!! error TS1003: Identifier expected.
~
!!! error TS1005: '>' expected.
~
!!! error TS2304: Cannot find name 'b'.
~
!!! error TS1109: Expression expected.
~~~
!!! error TS2304: Cannot find name 'a:b'.
~~~
!!! error TS2304: Cannot find name 'a:b'.
==== tests/cases/conformance/jsx/10.tsx (6 errors) ====
<a.b:c></a.b:c>;
~
Expand Down
5 changes: 2 additions & 3 deletions tests/baselines/reference/jsxInvalidEsprimaTestSuite.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,9 @@ a / > ;
//// [7.jsx]
<a foo="bar;/>;
//// [8.jsx]
<a b></b>;
<a:b></b>;
//// [9.jsx]
<a b c></a>;
b.c > ;
<a:b.c></a:b.c>;
//// [10.jsx]
<a.b c></a.b>;
c > ;
Expand Down
9 changes: 2 additions & 7 deletions tests/baselines/reference/jsxInvalidEsprimaTestSuite.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,9 @@ No type information for this code.=== tests/cases/conformance/jsx/7.tsx ===

=== tests/cases/conformance/jsx/8.tsx ===
<a:b></b>;
>b : Symbol(b, Decl(8.tsx, 0, 3))

=== tests/cases/conformance/jsx/9.tsx ===
No type information for this code.=== tests/cases/conformance/jsx/9.tsx ===
<a:b.c></a:b.c>;
>b : Symbol(b, Decl(9.tsx, 0, 3))
>c : Symbol(c, Decl(9.tsx, 0, 5))

=== tests/cases/conformance/jsx/10.tsx ===
No type information for this code.=== tests/cases/conformance/jsx/10.tsx ===
<a.b:c></a.b:c>;
>c : Symbol(c, Decl(10.tsx, 0, 5))

Expand Down
18 changes: 7 additions & 11 deletions tests/baselines/reference/jsxInvalidEsprimaTestSuite.types
Original file line number Diff line number Diff line change
Expand Up @@ -51,22 +51,18 @@ declare var React: any;
=== tests/cases/conformance/jsx/8.tsx ===
<a:b></b>;
><a:b></b> : any
>a : any
>b : true
>a:b : any
>b : any

=== tests/cases/conformance/jsx/9.tsx ===
<a:b.c></a:b.c>;
><a:b.c></a : any
>a : any
>b : true
>c : true
>a : any
>b.c> : boolean
>b.c : any
>b : any
><a:b.c></a:b.c> : any
>a:b.c : any
>a:b : any
>c : any
>a:b.c : any
>a:b : any
>c : any
> : any

=== tests/cases/conformance/jsx/10.tsx ===
<a.b:c></a.b:c>;
Expand Down
Loading