Revert "feat(ivy): support for i18n & ICU expressions (#26275)"

This reverts commit a63fd2d0f5.
This commit is contained in:
Miško Hevery 2018-11-14 10:23:21 -08:00
parent a752971bca
commit f8f1168fa6
25 changed files with 2563 additions and 3005 deletions

View File

@ -83,23 +83,23 @@ describe('i18n support in the view compiler', () => {
$r3$.ɵi18nEnd();
$r3$.ɵelementEnd();
$r3$.ɵelementStart(2, "div");
$r3$.ɵi18nAttributes(3, $_c2$);
$r3$.ɵi18nAttribute(3, $_c2$);
$r3$.ɵtext(4, "Content B");
$r3$.ɵelementEnd();
$r3$.ɵelementStart(5, "div");
$r3$.ɵi18nAttributes(6, $_c4$);
$r3$.ɵi18nAttribute(6, $_c4$);
$r3$.ɵtext(7, "Content C");
$r3$.ɵelementEnd();
$r3$.ɵelementStart(8, "div");
$r3$.ɵi18nAttributes(9, $_c6$);
$r3$.ɵi18nAttribute(9, $_c6$);
$r3$.ɵtext(10, "Content D");
$r3$.ɵelementEnd();
$r3$.ɵelementStart(11, "div");
$r3$.ɵi18nAttributes(12, $_c8$);
$r3$.ɵi18nAttribute(12, $_c8$);
$r3$.ɵtext(13, "Content E");
$r3$.ɵelementEnd();
$r3$.ɵelementStart(14, "div");
$r3$.ɵi18nAttributes(15, $_c10$);
$r3$.ɵi18nAttribute(15, $_c10$);
$r3$.ɵtext(16, "Content F");
$r3$.ɵelementEnd();
}
@ -142,7 +142,7 @@ describe('i18n support in the view compiler', () => {
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵelementStart(0, "div", $_c0$);
$r3$.ɵi18nAttributes(1, $_c2$);
$r3$.ɵi18nAttribute(1, $_c2$);
$r3$.ɵelementEnd();
}
}
@ -207,10 +207,10 @@ describe('i18n support in the view compiler', () => {
if (rf & 1) {
$r3$.ɵelementStart(0, "div", $_c0$);
$r3$.ɵpipe(1, "uppercase");
$r3$.ɵi18nAttributes(2, $_c4$);
$r3$.ɵi18nAttribute(2, $_c4$);
$r3$.ɵelementEnd();
$r3$.ɵelementStart(3, "div", $_c5$);
$r3$.ɵi18nAttributes(4, $_c8$);
$r3$.ɵi18nAttribute(4, $_c8$);
$r3$.ɵelementEnd();
}
if (rf & 2) {
@ -265,7 +265,7 @@ describe('i18n support in the view compiler', () => {
$r3$.ɵelementStart(0, "div");
$r3$.ɵelementStart(1, "div");
$r3$.ɵpipe(2, "uppercase");
$r3$.ɵi18nAttributes(3, $_c2$);
$r3$.ɵi18nAttribute(3, $_c2$);
$r3$.ɵelementEnd();
$r3$.ɵelementEnd();
}
@ -345,10 +345,10 @@ describe('i18n support in the view compiler', () => {
if (rf & 1) {
$r3$.ɵelementStart(0, "div", $_c0$);
$r3$.ɵpipe(1, "uppercase");
$r3$.ɵi18nAttributes(2, $_c4$);
$r3$.ɵi18nAttribute(2, $_c4$);
$r3$.ɵelementEnd();
$r3$.ɵelementStart(3, "div", $_c5$);
$r3$.ɵi18nAttributes(4, $_c8$);
$r3$.ɵi18nAttribute(4, $_c8$);
$r3$.ɵelementEnd();
}
if (rf & 2) {
@ -403,7 +403,7 @@ describe('i18n support in the view compiler', () => {
$r3$.ɵelementStart(0, "div");
$r3$.ɵelementStart(1, "div");
$r3$.ɵpipe(2, "uppercase");
$r3$.ɵi18nAttributes(3, $_c2$);
$r3$.ɵi18nAttribute(3, $_c2$);
$r3$.ɵelementEnd();
$r3$.ɵelementEnd();
}
@ -693,7 +693,7 @@ describe('i18n support in the view compiler', () => {
$r3$.ɵelementStart(0, "div");
$r3$.ɵi18nStart(1, $MSG_APP_SPEC_TS_0$);
$r3$.ɵelementStart(2, "span");
$r3$.ɵi18nAttributes(3, $_c2$);
$r3$.ɵi18nAttribute(3, $_c2$);
$r3$.ɵelementEnd();
$r3$.ɵi18nEnd();
$r3$.ɵelementEnd();
@ -701,7 +701,7 @@ describe('i18n support in the view compiler', () => {
$r3$.ɵi18nStart(5, $MSG_APP_SPEC_TS_3$);
$r3$.ɵpipe(6, "uppercase");
$r3$.ɵelementStart(7, "span");
$r3$.ɵi18nAttributes(8, $_c5$);
$r3$.ɵi18nAttribute(8, $_c5$);
$r3$.ɵelementEnd();
$r3$.ɵi18nEnd();
$r3$.ɵelementEnd();

View File

@ -95,7 +95,7 @@ export class Identifiers {
static pipeBind4: o.ExternalReference = {name: 'ɵpipeBind4', moduleName: CORE};
static pipeBindV: o.ExternalReference = {name: 'ɵpipeBindV', moduleName: CORE};
static i18nAttributes: o.ExternalReference = {name: 'ɵi18nAttributes', moduleName: CORE};
static i18nAttribute: o.ExternalReference = {name: 'ɵi18nAttribute', moduleName: CORE};
static i18nExp: o.ExternalReference = {name: 'ɵi18nExp', moduleName: CORE};
static i18nStart: o.ExternalReference = {name: 'ɵi18nStart', moduleName: CORE};
static i18nEnd: o.ExternalReference = {name: 'ɵi18nEnd', moduleName: CORE};

View File

@ -490,7 +490,7 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
if (i18nAttrArgs.length) {
const index: o.Expression = o.literal(this.allocateDataSlot());
const args = this.constantPool.getConstLiteral(o.literalArr(i18nAttrArgs), true);
this.creationInstruction(element.sourceSpan, R3.i18nAttributes, [index, args]);
this.creationInstruction(element.sourceSpan, R3.i18nAttribute, [index, args]);
if (hasBindings) {
this.updateInstruction(element.sourceSpan, R3.i18nApply, [index]);
}

View File

@ -108,12 +108,24 @@ export {
PipeDef as ɵPipeDef,
PipeDefWithMeta as ɵPipeDefWithMeta,
whenRendered as ɵwhenRendered,
i18nAttributes as ɵi18nAttributes,
i18nAttribute as ɵi18nAttribute,
i18nExp as ɵi18nExp,
i18nStart as ɵi18nStart,
i18nEnd as ɵi18nEnd,
i18nApply as ɵi18nApply,
i18nIcuReplaceVars as ɵi18nIcuReplaceVars,
i18nExpMapping as ɵi18nExpMapping,
i18nInterpolation1 as ɵi18nInterpolation1,
i18nInterpolation2 as ɵi18nInterpolation2,
i18nInterpolation3 as ɵi18nInterpolation3,
i18nInterpolation4 as ɵi18nInterpolation4,
i18nInterpolation5 as ɵi18nInterpolation5,
i18nInterpolation6 as ɵi18nInterpolation6,
i18nInterpolation7 as ɵi18nInterpolation7,
i18nInterpolation8 as ɵi18nInterpolation8,
i18nInterpolationV as ɵi18nInterpolationV,
i18nMapping as ɵi18nMapping,
I18nInstruction as ɵI18nInstruction,
I18nExpInstruction as ɵI18nExpInstruction,
WRAP_RENDERER_FACTORY2 as ɵWRAP_RENDERER_FACTORY2,
setClassMetadata as ɵsetClassMetadata,
} from './render3/index';

View File

@ -205,12 +205,12 @@ The goal is for the `@Component` (and friends) to be the compiler of template. S
### I18N
| Feature | Runtime | Spec | Compiler |
| ----------------------------------- | ------- | -------- | -------- |
| i18nStart | | ✅ | ✅ |
| i18nEnd | | ✅ | ✅ |
| i18nAttributes | | ✅ | ✅ |
| i18nExp | | ✅ | ✅ |
| i18nApply | | ✅ | ✅ |
| ICU expressions | | ✅ | ❌ |
| i18nStart | | ✅ | ✅ |
| i18nEnd | | ✅ | ✅ |
| i18nAttributes | | ✅ | ✅ |
| i18nExp | | ✅ | ✅ |
| i18nApply | | ✅ | ✅ |
| ICU expressions | | ✅ | ❌ |
| closure support for g3 | ✅ | ✅ | ❌ |
| runtime service for external world | ❌ | ❌ | ❌ |
| migration tool | ❌ | ❌ | ❌ |

View File

@ -12,11 +12,11 @@ For example index `123` may point to a component instance in the `LViewData` but
The layout is as such:
| Section | `LViewData` | `TView.data`
| ---------- | ------------------------------------------------------------ | --------------------------------------------------
| ---------- | --------------------------------------------- | --------------------------------------------------
| `HEADER` | contextual data | mostly `null`
| `CONSTS` | DOM, pipe, and local ref instances |
| `VARS` | binding values | property names
| `EXPANDO` | host bindings; directive instances; providers; dynamic nodes | host prop names; directive tokens; provider tokens; `null`
| `EXPANDO` | host bindings; directive instances; providers | host prop names; directive tokens; provider tokens
## `HEADER`

View File

@ -23,7 +23,7 @@ class MyComponent {
```
NOTE:
- There really is only two kinds of i18n text.
1. In attribute as in `title` (with `i18n-title` present).
1. In attribute as in `i18n-title`.
2. In element body marked as as `<div i18n>`.
- The element body i18n can have internal DOM structure which may consist of sub-templates.
@ -160,8 +160,8 @@ i18nAttributes(1, MSG_div_attr);
```
The above instruction checks the `TView.data` cache at position `1` and if empty will create `I18nUpdateOpCodes` like so:
```typescript
const i18nUpdateOpCodes = <I18nUpdateOpCodes>[
// The following OpCodes represent: `<div i18n-title title="Hello <20>0<EFBFBD>!">`
<I18nUpdateOpCodes>[
// The following OpCodes represent: `<div i18n-title="Hello <20>0<EFBFBD>!">`
// If `changeMask & 0b11`
// has changed then execute update OpCodes.
// has NOT changed then skip `7` values and start processing next OpCodes.
@ -170,13 +170,12 @@ const i18nUpdateOpCodes = <I18nUpdateOpCodes>[
'Hello ', // accumulate('Hello ');
-1, // accumulate(-1);
'!', // accumulate('!');
// Update attribute: `elementAttribute(0, 'title', accumulatorFlush(null));`
// Update attribute: `elementAttribute(1, 'title', accumulatorFlush(null));`
// NOTE: `null` means don't sanitize
0 << SHIFT_REF | Attr, 'title', null,
1 << SHIFT_REF | Attr, 'title', null,
]
```
NOTE:
- `i18nAttributes` updates the attributes of the previous element.
- If there is more than one attribute which needs to be internationalized it is added to the array as `[attributeName, translation]` tuple.
- Even attributes which don't have bindings must go through `i18nAttributes` so that they correctly work with i18n in server environment.
@ -217,7 +216,7 @@ will generate
```typescript
// Text broken down to allow addition of comments (Generated code will not have comments)
const MSG_div =
'List: ' +
'List: '
'<27>*2:1<>' + // template(2, MyComponent_NgIf_Template_0, ...);
'<27>#1:1<>' + // elementStart(1, 'ul');
'<27>*2:2<>' + // template(2, MyComponent_NgIf_NgFor_Template_1, ...);
@ -299,7 +298,7 @@ i18nEnd(); // The instruction which is responsible for inserting text node
The `i18nStart` generates these instructions which are cached in the `TView` and then processed by `i18nEnd`.
```typescript
const tI18n = <TI18n>{
<TI18n>{
vars: 2, // Number of slots to allocate in EXPANDO.
expandoStartIndex: 100, // Assume in this example EXPANDO starts at 100
create: <I18nMutateOpCodes>[ // Processed by `i18nEnd`
@ -363,7 +362,7 @@ This case is more complex because it contains an ICU.
ICUs are pre-parsed and then stored in the `TVIEW.data` as follows.
```typescript
const tI18n = <TI18n>{
<TI18n>{
vars: 3 + Math.max(4, 3, 3), // Number of slots to allocate in EXPANDO. (Max of all ICUs + fixed)
expandoStartIndex: 200, // Assume in this example EXPANDO starts at 200
create: <I18nMutateOpCodes>[
@ -380,16 +379,16 @@ const tI18n = <TI18n>{
// has NOT changed then skip `2` values and start processing next OpCodes.
0b1, 2,
-1, // accumulate(-1);
// Switch ICU: `icuSwitchCase(lViewData[200 /*SHIFT_REF*/], 0 /*SHIFT_ICU*/, accumulatorFlush());`
200 << SHIFT_REF | 0 << SHIFT_ICU | IcuSwitch,
// Switch ICU: `icuSwitchCase(lViewData[0 /*SHIFT_ICU*/], 0 /*SHIFT_REF*/, accumulatorFlush());`
0 << SHIFT_ICU | 0 << SHIFT_REF | IcuSwitch,
// NOTE: the bit mask here is the logical OR of all of the masks in the ICU.
0b1, 1,
// Update ICU: `icuUpdateCase(lViewData[200 /*SHIFT_REF*/], 0 /*SHIFT_ICU*/);`
// SHIFT_REF: points to: `i18nStart(0, MSG_div, 1);`
// SHIFT_ICU: is an index into which ICU is being updated. In our example we only have
// Update ICU: `icuUpdateCase(lViewData[0 /*SHIFT_ICU*/], 0 /*SHIFT_REF*/);`
// SHIFT_ICU: points to: `i18nStart(0, MSG_div, 1);`
// SHIFT_REF: is an index into which ICU is being updated. In our example we only have
// one ICU so it is 0-th ICU to update.
200 << SHIFT_REF | 0 << SHIFT_ICU | IcuUpdate,
0 << SHIFT_ICU | 0 << SHIFT_REF | IcuUpdate,
],
icus: [
<TIcu>{
@ -545,7 +544,7 @@ The OpCodes require that offsets for the EXPANDO index for the reference.
The question is how do we compute this:
```typescript
const tI18n = <TI18n>{
<TI18n>{
vars: 1,
expandoStartIndex: 100, // Retrieved from `tView.blueprint.length` at i18nStart invocation.
create: <I18nMutateOpCodes>[
@ -624,7 +623,7 @@ The rules for attribute ICUs should be the same as for normal ICUs.
For this reason we would like to reuse as much code as possible for parsing and processing of the ICU for simplicity and consistency.
```typescript
const tI18n = <TI18n>{
<TI18n>{
vars: 0, // Number of slots to allocate in EXPANDO. (Max of all ICUs + fixed)
expandoStartIndex: 200, // Assume in this example EXPANDO starts at 200
create: <I18nMutateOpCodes>[
@ -636,18 +635,18 @@ const tI18n = <TI18n>{
// has NOT changed then skip `2` values and start processing next OpCodes.
0b1, 2,
-1, // accumulate(-1)
// Switch ICU: `icuSwitchCase(lViewData[200 /*SHIFT_REF*/], 0 /*SHIFT_ICU*/, accumulatorFlush());`
200 << SHIFT_REF | 0 << SHIFT_ICU | IcuSwitch,
// Switch ICU: `icuSwitchCase(lViewData[0 /*SHIFT_ICU*/], 0 /*SHIFT_REF*/, accumulatorFlush());`
0 << SHIFT_ICU | 0 << SHIFT_REF | IcuSwitch,
// NOTE: the bit mask here is the logical OR of all of the masks in the ICU.
0b1, 4,
'You have ', // accumulate('You have ');
// Update ICU: `icuUpdateCase(lViewData[200 /*SHIFT_REF*/], 0 /*SHIFT_ICU*/);`
// SHIFT_REF: points to: `i18nStart(0, MSG_div, 1);`
// SHIFT_ICU: is an index into which ICU is being updated. In our example we only have
// Update ICU: `icuUpdateCase(lViewData[0 /*SHIFT_ICU*/], 0 /*SHIFT_REF*/);`
// SHIFT_ICU: points to: `i18nStart(0, MSG_div, 1);`
// SHIFT_REF: is an index into which ICU is being updated. In our example we only have
// one ICU so it is 0-th ICU to update.
200 << SHIFT_REF | 0 << SHIFT_ICU | IcuUpdate,
0 << SHIFT_ICU | 0 << SHIFT_REF | IcuUpdate,
'.', // accumulate('.');
@ -700,7 +699,7 @@ const tI18n = <TI18n>{
// has changed then execute update OpCodes.
// has NOT changed then skip `1` values and start processing next OpCodes.
-1, 2,
-1, // accumulate(lViewData[bindIndex-1]);
-1, // accumulate(lviewData[bindIndex-1]);
'emails', // accumulate('no emails');
]
]
@ -725,7 +724,7 @@ Given
```
The above needs to be parsed into:
```TypeScript
const icu = {
{
type: 'plural', // or 'select'
expressionBindingIndex: 0, // from <20>0<EFBFBD>,
cases: [
@ -758,7 +757,7 @@ NOTE: The updates to attributes with placeholders require that we go through san
## Translation without top level element
Placing `i18n` attribute on an existing elements is easy because the element defines parent and the translated element can be inserted synchronously.
Placing `i18n` attribute on an existing elements is easy because the element defines parent and the translated element can be insert synchronously.
For virtual elements such as `<ng-container>` or `<ng-template>` this is more complicated because there is no common root element to insert into.
In such a case the `i18nStart` acts as the element to insert into.
This is similar to `<ng-container>` behavior.
@ -784,7 +783,7 @@ function MyComponent_Template_0(rf: RenderFlags, ctx: any) {
Which would get parsed into:
```typescript
const tI18n = <TI18n>{
<TI18n>{
vars: 2, // Number of slots to allocate in EXPANDO.
expandoStartIndex: 100, // Assume in this example EXPANDO starts at 100
create: <I18nMutateOpCodes>[ // Processed by `i18nEnd`
@ -870,7 +869,7 @@ NOTE:
The internal data structure will be:
```typescript
const tI18n = <TI18n>{
<TI18n>{
vars: 2, // Number of slots to allocate in EXPANDO.
expandoStartIndex: 100, // Assume in this example EXPANDO starts at 100
create: <I18nMutateOpCodes>[ // Processed by `i18nEnd`
@ -882,16 +881,16 @@ const tI18n = <TI18n>{
// has NOT changed then skip `2` values and start processing next OpCodes.
0b1, 2,
-1, // accumulate(-1);
// Switch ICU: `icuSwitchCase(lViewData[100 /*SHIFT_REF*/], 0 /*SHIFT_ICU*/, accumulatorFlush());`
100 << SHIFT_REF | 0 << SHIFT_ICU | IcuSwitch,
// Switch ICU: `icuSwitchCase(lViewData[0 /*SHIFT_ICU*/], 0 /*SHIFT_REF*/, accumulatorFlush());`
0 << SHIFT_ICU | 0 << SHIFT_REF | IcuSwitch,
// NOTE: the bit mask here is the logical OR of all of the masks in the ICU.
0b1, 1,
// Update ICU: `icuUpdateCase(lViewData[100 /*SHIFT_REF*/], 0 /*SHIFT_ICU*/);`
// SHIFT_REF: points to: `i18nStart(0, MSG_div, 1);`
// SHIFT_ICU: is an index into which ICU is being updated. In our example we only have
// Update ICU: `icuUpdateCase(lViewData[0 /*SHIFT_ICU*/], 0 /*SHIFT_REF*/);`
// SHIFT_ICU: points to: `i18nStart(0, MSG_div, 1);`
// SHIFT_REF: is an index into which ICU is being updated. In our example we only have
// one ICU so it is 0-th ICU to update.
100 << SHIFT_REF | 0 << SHIFT_ICU | IcuUpdate,
0 << SHIFT_ICU | 0 << SHIFT_REF | IcuUpdate,
],
icus: [
<TIcu>{ // {<7B>0<EFBFBD>, plural, =0 {zero} other {<7B>0<EFBFBD> <!--subICU-->}}
@ -907,7 +906,7 @@ const tI18n = <TI18n>{
'', 1 << SHIFT_PARENT | AppendChild, // Expando location: 100
COMMENT_MARKER, '', 0 << SHIFT_PARENT | AppendChild, // Expando location: 101
],
],
]
remove: [
<I18nMutateOpCodes>[ // Case: `0`: `{zero}`
1 << SHIFT_PARENT | 100 << SHIFT_REF | Remove,
@ -922,16 +921,16 @@ const tI18n = <TI18n>{
],
<I18nMutateOpCodes>[ // Case: `other`: `{<7B>0<EFBFBD> <!--subICU-->}`
0b1, 3,
-2, ' ', 100 << SHIFT_REF | Text, // Case: `<60>0<EFBFBD> `
-2, ' ', 100 << SHIFT_REF | Text // Case: `<60>0<EFBFBD> `
0b10, 5,
-1,
// Switch ICU: `icuSwitchCase(lViewData[101 /*SHIFT_REF*/], 0 /*SHIFT_ICU*/, accumulatorFlush());`
101 << SHIFT_REF | 0 << SHIFT_ICU | IcuSwitch,
-1
// Switch ICU: `icuSwitchCase(lViewData[0 /*SHIFT_ICU*/], 1 /*SHIFT_REF*/, accumulatorFlush());`
0 << SHIFT_ICU | 1 << SHIFT_REF | IcuSwitch,
// NOTE: the bit mask here is the logical OR of all of the masks int the ICU.
0b10, 1,
// Update ICU: `icuUpdateCase(lViewData[101 /*SHIFT_REF*/], 0 /*SHIFT_ICU*/);`
101 << SHIFT_REF | 0 << SHIFT_ICU | IcuUpdate,
// Update ICU: `icuUpdateCase(lViewData[0 /*SHIFT_ICU*/], 1 /*SHIFT_REF*/);`
0 << SHIFT_ICU | 1 << SHIFT_REF | IcuUpdate,
],
]
},
@ -1058,7 +1057,7 @@ Here is a more complete example.
Given this Angular's template:
```HTML
<div i18n-title title="Hello {{name}}!" i18n="Some description.">
<div i18n-title="Hello {{name}}!" i18n="Some description.">
{{count}} is rendered as:
<b *ngIf="true">
{ count, plural,
@ -1112,7 +1111,7 @@ To generate code where the extracted i18n messages have the same ids, the `ngtsc
Given this Angular's template:
```HTML
<div i18n-title title="Hello {{name}}!" i18n="Some description.">
<div i18n-title="Hello {{name}}!" i18n="Some description.">
{{count}} is rendered as:
<b *ngIf="true">
{ count, plural,

File diff suppressed because it is too large Load Diff

View File

@ -87,12 +87,24 @@ export {
} from './state';
export {
i18nAttributes,
i18nAttribute,
i18nExp,
i18nStart,
i18nEnd,
i18nApply,
i18nIcuReplaceVars,
i18nMapping,
i18nInterpolation1,
i18nInterpolation2,
i18nInterpolation3,
i18nInterpolation4,
i18nInterpolation5,
i18nInterpolation6,
i18nInterpolation7,
i18nInterpolation8,
i18nInterpolationV,
i18nExpMapping,
I18nInstruction,
I18nExpInstruction
} from './i18n';
export {NgModuleFactory, NgModuleRef, NgModuleType} from './ng_module_ref';

View File

@ -7,6 +7,7 @@
*/
import './ng_dev_mode';
import {resolveForwardRef} from '../di/forward_ref';
import {InjectionToken} from '../di/injection_token';
import {InjectFlags} from '../di/injector_compatibility';
@ -15,6 +16,7 @@ import {Sanitizer} from '../sanitization/security';
import {StyleSanitizeFn} from '../sanitization/style_sanitizer';
import {Type} from '../type';
import {noop} from '../util/noop';
import {assertDefined, assertEqual, assertLessThan, assertNotEqual} from './assert';
import {attachPatchData, getComponentViewByInstance} from './context_discovery';
import {diPublicInInjector, getNodeInjectable, getOrCreateInjectable, getOrCreateNodeInjectorForNode, injectAttributeImpl} from './di';
@ -23,12 +25,11 @@ import {executeHooks, executeInitHooks, queueInitHooks, queueLifecycleHooks} fro
import {ACTIVE_INDEX, LContainer, VIEWS} from './interfaces/container';
import {ComponentDef, ComponentQuery, ComponentTemplate, DirectiveDef, DirectiveDefListOrFactory, InitialStylingFlags, PipeDefListOrFactory, RenderFlags} from './interfaces/definition';
import {INJECTOR_SIZE, NodeInjectorFactory} from './interfaces/injector';
import {AttributeMarker, InitialInputData, InitialInputs, LocalRefExtractor, PropertyAliasValue, PropertyAliases, TAttributes, TContainerNode, TElementContainerNode, TElementNode, TIcuContainerNode, TNode, TNodeFlags, TNodeProviderIndexes, TNodeType, TProjectionNode, TViewNode} from './interfaces/node';
import {AttributeMarker, InitialInputData, InitialInputs, LocalRefExtractor, PropertyAliasValue, PropertyAliases, TAttributes, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeProviderIndexes, TNodeType, TProjectionNode, TViewNode} from './interfaces/node';
import {PlayerFactory} from './interfaces/player';
import {CssSelectorList, NG_PROJECT_AS_ATTR_NAME} from './interfaces/projection';
import {LQueries} from './interfaces/query';
import {ProceduralRenderer3, RComment, RElement, RNode, RText, Renderer3, RendererFactory3, isProceduralRenderer} from './interfaces/renderer';
import {SanitizerFn} from './interfaces/sanitization';
import {StylingIndex} from './interfaces/styling';
import {BINDING_INDEX, CLEANUP, CONTAINER_INDEX, CONTENT_QUERIES, CONTEXT, DECLARATION_VIEW, FLAGS, HEADER_OFFSET, HOST, HOST_NODE, INJECTOR, LViewData, LViewFlags, NEXT, OpaqueViewState, PARENT, QUERIES, RENDERER, RootContext, RootContextFlags, SANITIZER, TAIL, TVIEW, TView} from './interfaces/view';
import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert';
@ -41,6 +42,7 @@ import {getStylingContext} from './styling/util';
import {NO_CHANGE} from './tokens';
import {getComponentViewByIndex, getNativeByIndex, getNativeByTNode, getRootContext, getRootView, getTNode, isComponent, isComponentDef, isDifferent, loadInternal, readPatchedLViewData, stringify} from './util';
/**
* A permanent marker promise which signifies that the current CD tree is
* clean.
@ -52,6 +54,11 @@ const enum BindingDirection {
Output,
}
/**
* Function used to sanitize the value before writing it into the renderer.
*/
type SanitizerFn = (value: any) => string;
/**
* Refreshes the view, executing the following steps in that order:
* triggers init hooks, refreshes dynamic embedded views, triggers content hooks, sets host
@ -190,13 +197,9 @@ export function createNodeAtIndex(
export function createNodeAtIndex(
index: number, type: TNodeType.ElementContainer, native: RComment, name: null,
attrs: TAttributes | null): TElementContainerNode;
export function createNodeAtIndex(
index: number, type: TNodeType.IcuContainer, native: RComment, name: null,
attrs: TAttributes | null): TElementContainerNode;
export function createNodeAtIndex(
index: number, type: TNodeType, native: RText | RElement | RComment | null, name: string | null,
attrs: TAttributes | null): TElementNode&TContainerNode&TElementContainerNode&TProjectionNode&
TIcuContainerNode {
attrs: TAttributes | null): TElementNode&TContainerNode&TElementContainerNode&TProjectionNode {
const viewData = getViewData();
const tView = getTView();
const adjustedIndex = index + HEADER_OFFSET;
@ -230,7 +233,7 @@ export function createNodeAtIndex(
setPreviousOrParentTNode(tNode);
setIsParent(true);
return tNode as TElementNode & TViewNode & TContainerNode & TElementContainerNode &
TProjectionNode & TIcuContainerNode;
TProjectionNode;
}
export function createViewNode(index: number, view: LViewData) {
@ -252,12 +255,11 @@ export function createViewNode(index: number, view: LViewData) {
* i18nApply() or ComponentFactory.create), we need to adjust the blueprint for future
* template passes.
*/
export function allocExpando(view: LViewData) {
export function adjustBlueprintForNewNode(view: LViewData) {
const tView = view[TVIEW];
if (tView.firstTemplatePass) {
tView.expandoStartIndex++;
tView.blueprint.push(null);
tView.data.push(null);
view.push(null);
}
}
@ -912,7 +914,7 @@ export function elementEnd(): void {
* @param sanitizer An optional function used to sanitize the value.
*/
export function elementAttribute(
index: number, name: string, value: any, sanitizer?: SanitizerFn | null): void {
index: number, name: string, value: any, sanitizer?: SanitizerFn): void {
if (value !== NO_CHANGE) {
const viewData = getViewData();
const renderer = getRenderer();
@ -945,7 +947,7 @@ export function elementAttribute(
*/
export function elementProperty<T>(
index: number, propName: string, value: T | NO_CHANGE, sanitizer?: SanitizerFn | null): void {
index: number, propName: string, value: T | NO_CHANGE, sanitizer?: SanitizerFn): void {
if (value === NO_CHANGE) return;
const viewData = getViewData();
const element = getNativeByIndex(index, viewData) as RElement | RComment;

View File

@ -16,32 +16,24 @@
*
* See: `I18nCreateOpCodes` for example of usage.
*/
import {SanitizerFn} from './sanitization';
export const enum I18nMutateOpCode {
/// Stores shift amount for bits 17-3 that contain reference index.
SHIFT_REF = 3,
/// Stores shift amount for bits 17-2 that contain reference index.
SHIFT_REF = 2,
/// Stores shift amount for bits 31-17 that contain parent index.
SHIFT_PARENT = 17,
/// Mask for OpCode
MASK_OPCODE = 0b111,
MASK_OPCODE = 0b11,
/// Mask for reference index.
MASK_REF = ((2 ^ 16) - 1) << SHIFT_REF,
/// OpCode to select a node. (next OpCode will contain the operation.)
Select = 0b000,
Select = 0b00,
/// OpCode to append the current node to `PARENT`.
AppendChild = 0b001,
AppendChild = 0b01,
/// OpCode to insert the current node to `PARENT` before `REF`.
InsertBefore = 0b010,
InsertBefore = 0b10,
/// OpCode to remove the `REF` node from `PARENT`.
Remove = 0b011,
/// OpCode to set the attribute of a node.
Attr = 0b100,
/// OpCode to simulate elementEnd()
ElementEnd = 0b101,
/// OpCode to read the remove OpCodes for the nested ICU
RemoveNestedIcu = 0b110,
Remove = 0b11,
}
/**
@ -122,8 +114,8 @@ export interface COMMENT_MARKER { marker: 'comment'; }
* // For removing existing nodes
* // --------------------------------------------------
* // const node = lViewData[1];
* // removeChild(tView.data(1), node, lViewData);
* 1 << SHIFT_REF | Remove,
* // lViewData[2].remove(node);
* 2 << SHIFT_PARENT | 1 << SHIFT_REF | Remove,
*
* // For writing attributes
* // --------------------------------------------------
@ -186,7 +178,7 @@ export const enum I18nUpdateOpCode {
* }
* ```
* We can assume that each call to `i18nExp` sets an internal `changeMask` bit depending on the
* index of `i18nExp`.
* index of `i18nExp` index.
*
* OpCodes
* ```
@ -230,7 +222,7 @@ export const enum I18nUpdateOpCode {
* ```
*
*/
export interface I18nUpdateOpCodes extends Array<string|number|SanitizerFn|null> {}
export interface I18nUpdateOpCodes extends Array<string|number|((text: string) => string | null)> {}
/**
* Store information for the i18n translation block.
@ -363,6 +355,10 @@ export interface TIcu {
update: I18nUpdateOpCodes[];
}
// Note: This hack is necessary so we don't erroneously get a circular dependency
// failure based on types.
export const unusedValueExportToPlacateAjd = 1;
/**
* Stores currently selected case in each ICU.
*
* For each ICU in translation, the `Li18n` stores the currently selected case for the current
* `LView`. For perf reasons this array is only created if a translation block has an ICU.
*/
export interface LI18n extends Array<number> {}

View File

@ -21,7 +21,6 @@ export const enum TNodeType {
Element = 0b011,
ViewOrElement = 0b010,
ElementContainer = 0b100,
IcuContainer = 0b101,
}
/**
@ -256,7 +255,7 @@ export interface TNode {
parent: TElementNode|TContainerNode|null;
/**
* If this node is part of an i18n block, it indicates whether this node is part of the DOM.
* If this node is part of an i18n block, it indicates whether this container is part of the DOM
* If this node is not part of an i18n block, this field is null.
*/
detached: boolean|null;
@ -359,6 +358,7 @@ export interface TContainerNode extends TNode {
projection: null;
}
/** Static data for an <ng-container> */
export interface TElementContainerNode extends TNode {
/** Index in the LViewData[] array. */
@ -369,21 +369,6 @@ export interface TElementContainerNode extends TNode {
projection: null;
}
/** Static data for an ICU expression */
export interface TIcuContainerNode extends TNode {
/** Index in the LViewData[] array. */
index: number;
child: TElementNode|TTextNode|null;
parent: TElementNode|TElementContainerNode|null;
tViews: null;
projection: null;
/**
* Indicates the current active case for an ICU expression.
* It is null when there is no active case.
*/
activeCaseIndex: number|null;
}
/** Static data for a view */
export interface TViewNode extends TNode {
/** If -1, it's a dynamically created view. Otherwise, it is the view block ID. */

View File

@ -1,12 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* Function used to sanitize the value before writing it into the renderer.
*/
export type SanitizerFn = (value: any) => string;

View File

@ -11,9 +11,9 @@ import {Injector} from '../../di/injector';
import {QueryList} from '../../linker';
import {Sanitizer} from '../../sanitization/security';
import {Type} from '../../type';
import {LContainer} from './container';
import {ComponentDef, ComponentQuery, ComponentTemplate, DirectiveDef, DirectiveDefList, HostBindingsFunction, PipeDef, PipeDefList} from './definition';
import {I18nUpdateOpCodes, TI18n} from './i18n';
import {TElementNode, TNode, TViewNode} from './node';
import {PlayerHandler} from './player';
import {LQueries} from './query';
@ -297,7 +297,7 @@ export interface TView {
/** Whether or not this template has been processed. */
firstTemplatePass: boolean;
/** Static data equivalent of LView.data[]. Contains TNodes, PipeDefInternal or TI18n. */
/** Static data equivalent of LView.data[]. Contains TNodes. */
data: TData;
/**
@ -535,7 +535,7 @@ export type HookData = (number | (() => void))[];
*/
export type TData =
(TNode | PipeDef<any>| DirectiveDef<any>| ComponentDef<any>| number | Type<any>|
InjectionToken<any>| TI18n | I18nUpdateOpCodes | null)[];
InjectionToken<any>| null)[];
// Note: This hack is necessary so we don't erroneously get a circular dependency
// failure based on types.

View File

@ -97,7 +97,7 @@ export const angularCoreEnv: {[name: string]: Function} = {
'ɵtextBinding': r3.textBinding,
'ɵembeddedViewStart': r3.embeddedViewStart,
'ɵembeddedViewEnd': r3.embeddedViewEnd,
'ɵi18nAttributes': r3.i18nAttributes,
'ɵi18nAttribute': r3.i18nAttribute,
'ɵi18nExp': r3.i18nExp,
'ɵi18nStart': r3.i18nStart,
'ɵi18nEnd': r3.i18nEnd,

View File

@ -21,23 +21,8 @@ const unusedValueToPlacateAjd = unused1 + unused2 + unused3 + unused4 + unused5;
/** Retrieves the parent element of a given node. */
export function getParentNative(tNode: TNode, currentView: LViewData): RElement|RComment|null {
if (tNode.parent == null) {
return getHostNative(currentView);
} else {
const parentTNode = getFirstParentNative(tNode);
return getNativeByTNode(parentTNode, currentView);
}
}
/**
* Get the first parent of a node that isn't an IcuContainer TNode
*/
function getFirstParentNative(tNode: TNode): TNode {
let parent = tNode.parent;
while (parent && parent.type === TNodeType.IcuContainer) {
parent = parent.parent;
}
return parent !;
return tNode.parent == null ? getHostNative(currentView) :
getNativeByTNode(tNode.parent, currentView);
}
/**
@ -593,22 +578,17 @@ function canInsertNativeChildOfView(viewTNode: TViewNode, view: LViewData): bool
*
*
* @param tNode The tNode of the node that we want to insert.
* @param parent The parent where the child will be inserted into.
* @param currentView Current LView being processed.
* @return boolean Whether the node should be inserted now (or delayed until later).
* @return boolean Whether the child should be inserted now (or delayed until later).
*/
export function canInsertNativeNode(tNode: TNode, currentView: LViewData): boolean {
let currentNode = tNode;
let parent: TNode|null = tNode.parent;
if (tNode.parent) {
if (tNode.parent.type === TNodeType.ElementContainer) {
if (tNode.parent && tNode.parent.type === TNodeType.ElementContainer) {
currentNode = getHighestElementContainer(tNode);
parent = currentNode.parent;
} else if (tNode.parent.type === TNodeType.IcuContainer) {
currentNode = getFirstParentNative(currentNode);
parent = currentNode.parent;
}
}
if (parent === null) parent = currentView[HOST_NODE];
@ -659,7 +639,7 @@ export function nativeNextSibling(renderer: Renderer3, node: RNode): RNode|null
* @returns Whether or not the child was appended
*/
export function appendChild(
childEl: RNode | null = null, childTNode: TNode, currentView: LViewData): boolean {
childEl: RNode | null, childTNode: TNode, currentView: LViewData): boolean {
if (childEl !== null && canInsertNativeNode(childTNode, currentView)) {
const renderer = currentView[RENDERER];
const parentEl = getParentNative(childTNode, currentView);
@ -675,9 +655,6 @@ export function appendChild(
} else if (parentTNode.type === TNodeType.ElementContainer) {
const renderParent = getRenderParent(childTNode, currentView) !;
nativeInsertBefore(renderer, renderParent, childEl, parentEl);
} else if (parentTNode.type === TNodeType.IcuContainer) {
const icuAnchorNode = getNativeByTNode(childTNode.parent !, currentView) !as RElement;
nativeInsertBefore(renderer, parentEl as RElement, childEl, icuAnchorNode);
} else {
isProceduralRenderer(renderer) ? renderer.appendChild(parentEl !as RElement, childEl) :
parentEl !.appendChild(childEl);

View File

@ -157,10 +157,6 @@ export function getCurrentView(): OpaqueViewState {
return viewData as any as OpaqueViewState;
}
export function _getViewData(): LViewData {
return viewData;
}
/**
* Restores `contextViewData` to the given OpaqueViewState instance.
*

View File

@ -250,15 +250,3 @@ export const defaultScheduler =
(typeof requestAnimationFrame !== 'undefined' && requestAnimationFrame || // browser only
setTimeout // everything else
).bind(global);
/**
* Equivalent to ES6 spread, add each item to an array.
*
* @param items The items to add
* @param arr The array to which you want to add the items
*/
export function addAllToArray(items: any[], arr: any[]) {
for (let i = 0; i < items.length; i++) {
arr.push(items[i]);
}
}

View File

@ -57,14 +57,14 @@ const INLINE_ELEMENTS = merge(
'bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,picture,q,ruby,rp,rt,s,' +
'samp,small,source,span,strike,strong,sub,sup,time,track,tt,u,var,video'));
export const VALID_ELEMENTS =
const VALID_ELEMENTS =
merge(VOID_ELEMENTS, BLOCK_ELEMENTS, INLINE_ELEMENTS, OPTIONAL_END_TAG_ELEMENTS);
// Attributes that have href and hence need to be sanitized
export const URI_ATTRS = tagSet('background,cite,href,itemtype,longdesc,poster,src,xlink:href');
const URI_ATTRS = tagSet('background,cite,href,itemtype,longdesc,poster,src,xlink:href');
// Attributes that have special href set hence need to be sanitized
export const SRCSET_ATTRS = tagSet('srcset');
const SRCSET_ATTRS = tagSet('srcset');
const HTML_ATTRS = tagSet(
'abbr,accesskey,align,alt,autoplay,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,' +
@ -81,7 +81,7 @@ const HTML_ATTRS = tagSet(
// can be sanitized, but they increase security surface area without a legitimate use case, so they
// are left out here.
export const VALID_ATTRS = merge(URI_ATTRS, SRCSET_ATTRS, HTML_ATTRS);
const VALID_ATTRS = merge(URI_ATTRS, SRCSET_ATTRS, HTML_ATTRS);
/**
* SanitizingHtmlSerializer serializes a DOM fragment, stripping out any unsafe elements and unsafe
@ -265,7 +265,7 @@ export function _sanitizeHtml(defaultDoc: any, unsafeHtmlInput: string): string
}
}
export function getTemplateContent(el: Node): Node|null {
function getTemplateContent(el: Node): Node|null {
return 'content' in (el as any /** Microsoft/TypeScript#21517 */) && isTemplateElement(el) ?
el.content :
null;

View File

@ -623,9 +623,6 @@
{
"name": "getElementDepthCount"
},
{
"name": "getFirstParentNative"
},
{
"name": "getFirstTemplatePass"
},

View File

@ -260,9 +260,6 @@
{
"name": "getDirectiveDef"
},
{
"name": "getFirstParentNative"
},
{
"name": "getFirstTemplatePass"
},

View File

@ -845,9 +845,6 @@
{
"name": "getErrorLogger"
},
{
"name": "getFirstParentNative"
},
{
"name": "getFirstTemplatePass"
},
@ -1107,7 +1104,7 @@
"name": "markViewDirty"
},
{
"name": "merge$1"
"name": "merge"
},
{
"name": "mergeAll"

View File

@ -665,9 +665,6 @@
{
"name": "getElementDepthCount"
},
{
"name": "getFirstParentNative"
},
{
"name": "getFirstTemplatePass"
},

View File

@ -678,7 +678,7 @@
"name": "PlatformRef"
},
{
"name": "Plural$1"
"name": "Plural"
},
{
"name": "QUERIES"
@ -1688,9 +1688,6 @@
{
"name": "getErrorLogger"
},
{
"name": "getFirstParentNative"
},
{
"name": "getFirstTemplatePass"
},
@ -1854,7 +1851,7 @@
"name": "getPlayerContext"
},
{
"name": "getPluralCategory$1"
"name": "getPluralCategory"
},
{
"name": "getPointers"

File diff suppressed because it is too large Load Diff