Commit Graph

764 Commits

Author SHA1 Message Date
JoostK 32ce8b1326 feat(compiler): add dependency info and ng-content selectors to metadata (#35695)
This commit augments the `FactoryDef` declaration of Angular decorated
classes to contain information about the parameter decorators used in
the constructor. If no constructor is present, or none of the parameters
have any Angular decorators, then this will be represented using the
`null` type. Otherwise, a tuple type is used where the entry at index `i`
corresponds with parameter `i`. Each tuple entry can be one of two types:

1. If the associated parameter does not have any Angular decorators,
   the tuple entry will be the `null` type.
2. Otherwise, a type literal is used that may declare at least one of
   the following properties:
   - "attribute": if `@Attribute` is present. The injected attribute's
   name is used as string literal type, or the `unknown` type if the
   attribute name is not a string literal.
   - "self": if `@Self` is present, always of type `true`.
   - "skipSelf": if `@SkipSelf` is present, always of type `true`.
   - "host": if `@Host` is present, always of type `true`.
   - "optional": if `@Optional` is present, always of type `true`.

   A property is only present if the corresponding decorator is used.

   Note that the `@Inject` decorator is currently not included, as it's
   non-trivial to properly convert the token's value expression to a
   type that is valid in a declaration file.

Additionally, the `ComponentDefWithMeta` declaration that is created for
Angular components has been extended to include all selectors on
`ng-content` elements within the component's template.

This additional metadata is useful for tooling such as the Angular
Language Service, as it provides the ability to offer suggestions for
directives/components defined in libraries. At the moment, such
tooling extracts the necessary information from the _metadata.json_
manifest file as generated by ngc, however this metadata representation
is being replaced by the information emitted into the declaration files.

Resolves FW-1870

PR Close #35695
2020-03-24 14:21:42 -07:00
Sonu Kapoor fced8ee40e fix(localize): allow ICU expansion case to start with any character except `}` (#36123)
Previously, an expansion case could only start with an alpha numeric character.
This commit fixes this by allowing an expansion case to start with any character
except `}`.

The [ICU spec](http://userguide.icu-project.org/formatparse/messages) is pretty vague:

> Use a "select" argument to select sub-messages via a fixed set of keywords.

It does not specify what can be a "keyword" but from looking at the surrounding syntax it
appears that it can indeed be any string that does not contain a `}` character.

Closes #31586

PR Close #36123
2020-03-23 11:37:12 -07:00
Keen Yee Liau d714b95fb9 feat(compiler): Propagate value span of ExpressionBinding to ParsedProperty (#36133)
This commit propagates the correct value span in an ExpressionBinding of
a microsyntax expression to ParsedProperty, which in turn porpagates the
span to the template ASTs (both VE and Ivy).

PR Close #36133
2020-03-20 10:21:11 -07:00
ayazhafiz df890d7629 fix(compiler): record correct end of expression (#34690)
This commit fixes a bug with the expression parser wherein the end index
of an expression node was recorded as the start index of the next token,
not the end index of the current token.

Closes #33477
Closes https://github.com/angular/vscode-ng-language-service/issues/433

PR Close #34690
2020-03-20 10:19:02 -07:00
danranVm 47bfec4e46 feat(core): add `isPromise` generic (#34168)
This commit adds generic to `isPromise` function to help with type inference.

PR Close #34168
2020-03-20 10:15:01 -07:00
Keen Yee Liau 31bec8ce61 feat(compiler): Propagate source span and value span to Variable AST (#36047)
This commit propagates the `sourceSpan` and `valueSpan` of a `VariableBinding`
in a microsyntax expression to `ParsedVariable`, and subsequently to
View Engine Variable AST and Ivy Variable AST.

Note that this commit does not propagate the `keySpan`, because it involves
significant changes to the template AST.

PR Close #36047
2020-03-16 10:52:57 -07:00
Ayaz Hafiz e179c5827f fix(compiler): do not recurse to find static symbols of same module (#35262)
To create the symbols of a module, the static symbol resolver first gets
all the symbols loaded in the module by an export statement. For `export
* from './module'`-like statements, all symbols from `./module` must be
loaded. In cases where the exporting module is actually the same module
that the export statement is in, this causes an unbounded recursive
resolution of the same module.

Exports of the same module are not needed, as their symbols will be
resolved when the symbols in the module metadata's `metadata` key is
explored.

This commit resolves the unbounded recursion by loading exporting
modules only if they differ from the module currently being resolved.

Closes https://github.com/angular/vscode-ng-language-service/issues/593

PR Close #35262
2020-03-16 10:52:23 -07:00
Andrew Kushnir 79659ee5aa fix(compiler): support directive inputs with interpolations on `<ng-template>`s (#35984)
Prior to this commit, Ivy compiler didn't handle directive inputs with interpolations located on `<ng-template>` elements (e.g. `<ng-template dir="{{ field }}">`). That was the case for regular inputs as well as inputs that should be processed via i18n subsystem (e.g. `<ng-template i18n-dir dir="Hello {{ name }}">`). This commit adds support for such expressions for explicit `<ng-template>`s as well as a number of tests to confirm the behavior.

Fixes #35752.

PR Close #35984
2020-03-16 10:51:18 -07:00
Keen Yee Liau 06779cfe24 feat(compiler): Add sourceSpan and keySpan to TemplateBinding (#35897)
This commit adds fine-grained text spans to TemplateBinding for microsyntax expressions.

1. Source span
   By convention, source span refers to the entire span of the binding,
   including its key and value.
2. Key span
   Span of the binding key, without any whitespace or keywords like `let`

The value span is captured by the value expression AST.

This is part of a series of PRs to fix source span mapping in microsyntax expression.
For more info, see the doc https://docs.google.com/document/d/1mEVF2pSSMSnOloqOPQTYNiAJO0XQxA1H0BZyESASOrE/edit?usp=sharing

PR Close #35897
2020-03-11 14:51:56 -04:00
Keen Yee Liau 81cb54fc15 refactor(compiler): optionalOperator -> consumeOptionalOperator (#35980)
PR Close #35980
2020-03-10 13:27:37 -04:00
Ayaz Hafiz 11f7e275e6 feat(compiler): type TemplateAst values as ASTWithSource (#35892)
TemplateAst values are currently typed as the base class AST, but they
are actually constructed with ASTWithSource. Type them as such, because
ASTWithSource gives more information about the consumed expression AST
to downstream customers (namely, the expression AST source).

Unblocks #35271

PR Close #35892
2020-03-09 12:14:09 -04:00
Keen Yee Liau bef14cf424 refactor(compiler): rename _ParseAST.optionalCharacter TemplateBinding.expression (#35886)
This commit renames
1. _ParseAST.optionalCharacter -> consumeOptionalCharacter
2. TemplateBinding.expression -> value

PR Close #35886
2020-03-06 12:39:49 -05:00
Keen Yee Liau 716d50aa21 refactor(compiler): Break up parseTemplateBindings() for microsyntax (#35812)
This commit is purely a refactoring of the logic in
`parseTemplateBindings` method for parsing the microsyntax expression.
This is done to enable the introduction of `keySpan` and `valueSpan` in
subsequent PR.

For a detailed explanation of this work and the subsequent work items,
please see https://docs.google.com/document/d/1mEVF2pSSMSnOloqOPQTYNiAJO0XQxA1H0BZyESASOrE/edit?usp=sharing

PR Close #35812
2020-03-05 16:04:41 -05:00
Doug Parker 9cf85d2177 fix(core): remove side effects from `ɵɵNgOnChangesFeature()` (#35769)
`ɵɵNgOnChangesFeature()` would set `ngInherit`, which is a side effect and also not necessary. This was pulled out to module scope so the function itself can be pure. Since it only curries another function, the call is entirely unnecessary. Updated the compiler to only generate a reference to this function, rather than a call to it, and removed the extra curry indirection.

PR Close #35769
2020-03-03 08:50:03 -08:00
Miško Hevery a153b61098 fix(core): treat `[class]` and `[className]` as unrelated bindings (#35668)
Before this change `[class]` and `[className]` were both converted into `ɵɵclassMap`. The implication of this is that at runtime we could not differentiate between the two and as a result we treated `@Input('class')` and `@Input('className)` as equivalent.

This change makes `[class]` and `[className]` distinct. The implication of this is that `[class]` becomes `ɵɵclassMap` instruction but  `[className]` becomes `ɵɵproperty' instruction. This means that `[className]` will no longer participate in styling and will overwrite the DOM `class` value.

Fix #35577

PR Close #35668
2020-03-02 08:18:59 -08:00
Andrew Kushnir 40da51f641 fix(compiler): support i18n attributes on `<ng-template>` tags (#35681)
Prior to this commit, i18n attributes defined on `<ng-template>` tags were not processed by the compiler. This commit adds the necessary logic to handle i18n attributes in the same way how these attrs are processed for regular elements.

PR Close #35681
2020-03-02 08:18:06 -08:00
Keen Yee Liau 208ef7bd62 refactor(compiler): Remove NullAstVisitor and visitAstChildren (#35619)
This commit removes the `NullAstVisitor` and `visitAstChildren` exported
from `packages/compiler/src/expression_parser/ast.ts` because they
contain duplicate and buggy implementation, and their use cases could be
sufficiently covered by `RecursiveAstVisitor` if the latter implements the
`visit` method. This use case is only needed in the language service.

With this change, any visitor that extends `RecursiveAstVisitor` could
just define their own `visit` function and the parent class will behave
correctly.

A bit of historical context:
In language service, we need a way to tranverse the expression AST in a
selective manner based on where the user's cursor is. This means we need a
"filtering" function to decide which node to visit and which node to not
visit. Instead of refactoring `RecursiveAstVisitor` to support this,
`visitAstChildren` was created. `visitAstChildren` duplicates the
implementation of `RecursiveAstVisitor`, but introduced some bugs along
the way. For example, in `visitKeyedWrite`, it visits
```
obj -> key -> obj
```
instead of
```
obj -> key -> value
```

Moreover, because of the following line
```
visitor.visit && visitor.visit(ast, context) || ast.visit(visitor, context);
```
`visitAstChildren` visits every node *twice*.

PR Close #35619
2020-02-28 07:13:17 -08:00
crisbeto 22786c8e88 fix(ivy): incorrectly generating shared pure function between null and object literal (#35481)
In #33705 we made it so that we generate pure functions for object/array literals in order to avoid having them be shared across elements/views. The problem this introduced is that further down the line the `ContantPool` uses the generated literal in order to figure out whether to share an existing factory or to create a new one. `ConstantPool` determines whether to share a factory by creating a key from the AST node and using it to look it up in the factory cache, however the key generation function didn't handle function invocations and replaced them with `null`. This means that the key for `{foo: pureFunction0(...)}` and `{foo: null}` are the same.

These changes rework the logic so that instead of generating a `null` key
for function invocations, we generate a variable called `<unknown>` which
shouldn't be able to collide with anything.

Fixes #35298.

PR Close #35481
2020-02-20 15:23:58 -08:00
Kristiyan Kostadinov 9228d7f15d perf(ivy): remove unused event argument in listener instructions (#35097)
Currently Ivy always generates the `$event` function argument, even if it isn't being used by the listener expressions. This can lead to unnecessary bytes being generated, because optimizers won't remove unused arguments by default. These changes add some logic to avoid adding the argument when it isn't required.

PR Close #35097
2020-02-20 15:22:13 -08:00
Miško Hevery 2562a3b1b0 fix(ivy): Add `style="{{exp}}"` based interpolation (#34202)
Fixes #33575

Add support for interpolation in styles as shown:
```
<div style="color: {{exp1}}; width: {{exp2}};">
```

PR Close #34202
2020-02-20 15:13:10 -08:00
ayazhafiz a92d97cda7 fix(compiler): report errors for missing binding names (#34595)
Currently, would-be binding attributes that are missing binding names
are not parsed as bindings, and fall through as regular attributes. In
some cases, this can lead to a runtime error; trying to assign `#` as a
DOM attribute in an element like in `<div #></div>` fails because `#` is
not a valid attribute name.

Attributes composed of binding prefixes but not defining a binding
should be considered invalid, as this almost certainly indicates an
unintentional elision of a binding by the developer. This commit
introduces error reporting for attributes with a binding name prefix but
no actual binding name.

Closes https://github.com/angular/vscode-ng-language-service/issues/293.

PR Close #34595
2020-02-10 16:29:32 -08:00
Kristiyan Kostadinov 304584c291 perf(ivy): remove unused argument in hostBindings function (#34969)
We had some logic for generating and passing in the `elIndex` parameter into the `hostBindings` function, but it wasn't actually being used for anything. The only place left that had a reference to it was the `StylingBuilder` and it only stored it without referencing it again.

PR Close #34969
2020-01-27 12:49:35 -08:00
Miško Hevery 9bd9590767 refactor(ivy): change styling to use programmatic API on updates (#34804)
Previously we would write to class/style as strings `element.className` and `element.style.cssText`. Turns out that approach is good for initial render but not good for updates. Updates using this approach are problematic because we have to check to see if there was an out of bound write to style and than perform reconciliation. This also requires the browser to bring up CSS parser which is expensive.

Another problem with old approach is that we had to queue the DOM writes and flush them twice. Once on element advance instruction and once in `hostBindings`. The double flushing is expensive but it also means that a directive can observe that styles are not yet written (they are written after directive executes.)

The new approach uses `element.classList.add/remove` and `element.style.setProperty/removeProperty` API for updates only (it continues to use `element.className` and `element.style.cssText` for initial render as it is cheaper.) The other change is that the styling changes are applied immediately (no queueing). This means that it is the instruction which computes priority. In some circumstances it may result in intermediate writes which are than overwritten with new value. (This should be rare)

Overall this change deletes most of the previous code and replaces it with new simplified implement. The simplification results in code savings.

PR Close #34804
2020-01-24 12:23:19 -08:00
Miško Hevery 5aabe93abe refactor(ivy): Switch styling to new reconcile algorithm (#34616)
NOTE: This change must be reverted with previous deletes so that it code remains in build-able state.

This change deletes old styling code and replaces it with a simplified styling algorithm.

The mental model for the new algorithm is:
- Create a linked list of styling bindings in the order of priority. All styling bindings ere executed in compiled order and than a linked list of bindings is created in priority order.
- Flush the style bindings at the end of `advance()` instruction. This implies that there are two flush events. One at the end of template `advance` instruction in the template. Second one at the end of `hostBindings` `advance` instruction when processing host bindings (if any).
- Each binding instructions effectively updates the string to represent the string at that location. Because most of the bindings are additive, this is a cheap strategy in most cases. In rare cases the strategy requires removing tokens from the styling up to this point. (We expect that to be rare case)S Because, the bindings are presorted in the order of priority, it is safe to resume the processing of the concatenated string from the last change binding.

PR Close #34616
2020-01-24 12:23:00 -08:00
Matias Niemelä 4005815114 refactor(ivy): generate 2 slots per styling instruction (#34616)
Compiler keeps track of number of slots (`vars`) which are needed for binding instructions. Normally each binding instructions allocates a single slot in the `LView` but styling instructions need to allocate two slots.

PR Close #34616
2020-01-24 12:22:44 -08:00
Miško Hevery 2961bf06c6 refactor(ivy): move `hostVars`/`hostAttrs` from instruction to `DirectiveDef` (#34683)
This change moves information from instructions to declarative position:
- `ɵɵallocHostVars(vars)` => `DirectiveDef.hostVars`
- `ɵɵelementHostAttrs(attrs)` => `DirectiveDef.hostAttrs`

When merging directives it is necessary to know about `hostVars` and `hostAttrs`. Before this change the information was stored in the `hostBindings` function. This was problematic, because in order to get to the information the `hostBindings` would have to be executed. In order for `hostBindings` to be executed the directives would have to be instantiated. This means that the directive instantiation would happen before we had knowledge about the `hostAttrs` and as a result the directive could observe in the constructor that not all of the `hostAttrs` have been applied. This further complicates the runtime as we have to apply `hostAttrs` in parts over many invocations.

`ɵɵallocHostVars` was unnecessarily complicated because it would have to update the `LView` (and Blueprint) while existing directives are already executing. By moving it out of `hostBindings` function we can access it statically and we can create correct `LView` (and Blueprint) in a single pass.

This change only changes how the instructions are generated, but does not change the runtime much. (We cheat by emulating the old behavior by calling `ɵɵallocHostVars` and `ɵɵelementHostAttrs`) Subsequent change will refactor the runtime to take advantage of the static information.

PR Close #34683
2020-01-24 12:22:10 -08:00
Misko Hevery 76698d38f7 refactor(ivy): Add style reconciliation algorithm (#34004)
This change introduces class/style reconciliation algorithm for DOM elements.
NOTE: The code is not yet hooked up, it will be used by future style algorithm.

Background:
Styling algorithm currently has [two paths](https://hackmd.io/@5zDGNGArSxiHhgvxRGrg-g/rycZk3N5S)
when computing how the style should be rendered.
1. A direct path which concatenates styling and uses `elemnent.className`/`element.style.cssText` and
2. A merge path which uses internal data structures and uses `element.classList.add/remove`/`element.style[property]`.

The situation is confusing and hard to follow/maintain. So a future PR will remove the merge-path and do everything with
direct-path. This however breaks when some other code adds class or style to the element without Angular's knowledge.
If this happens instead of switching from direct-path to merge-path algorithm, this change provides a different mental model
whereby we always do `direct-path` but the code which writes to the DOM detects the situation and reconciles the out of bound write.

The reconciliation process is as follows:
1. Detect that no one has modified `className`/`cssText` and if so just write directly (fast path).
2. If out of bounds write did occur, switch from writing using `className`/`cssText` to `element.classList.add/remove`/`element.style[property]`.
   This does require that the write function computes the difference between the previous Angular expected state and current Angular state.
   (This requires a parser. The advantage of having a parser is that we can support `style="width: {{exp}}px" kind of bindings.`)
   Compute the diff and apply it in non destructive way using `element.classList.add/remove`/`element.style[property]`

Properties of approach:
- If no out of bounds style modification:
  - Very fast code path: Just concatenate string in right order and write them to DOM.
  - Class list order is preserved
- If out of bounds style modification detected:
  - Penalty for parsing
  - Switch to non destructive modification: `element.classList.add/remove`/`element.style[property]`
  - Switch to alphabetical way of setting classes.

PR Close #34004
2020-01-24 12:21:39 -08:00
Matias Niemelä 32489c7426 revert: refactor(ivy): remove styleSanitizer instruction in favor of an inline param (#34480) (#34910)
This reverts commit 84d24c08e1.

PR Close #34910
2020-01-22 15:59:33 -05:00
Matias Niemelä 84d24c08e1 refactor(ivy): remove styleSanitizer instruction in favor of an inline param (#34480)
This patch removes the need for the styleSanitizer() instruction in
favor of passing the sanitizer into directly into the styleProp
instruction.

This patch also increases the binding index size for all style/class bindings in preparation for #34418

PR Close #34480
2020-01-22 14:35:00 -05:00
Andrew Kushnir 39ec188003 fix(ivy): more accurate detection of pipes in host bindings (#34655)
Pipes in host binding expressions are not supported in View Engine and Ivy, but in some more complex cases (like `(value | pipe) === true`) compiler was not reporting errors. This commit extends Ivy logic to detect pipes in host binding expressions and throw in cases bindings are present. View Engine behavior remains the same.

PR Close #34655
2020-01-21 13:22:00 -05:00
Igor Minar 63c9c2d2be fix: work around 'noImplicityAny' incompatibility due to ts3.7 update (#34798)
Typescript 3.7 now emits d.ts files for getters differently than prior versions,
and there seems to be a bug in how it strips private types without replacing them
with explicit 'any' type. This then leads to compilation failures in projects compiled
against our packages that don't have skipLibCheck turned on but do have strict or
noImplicitAny check on.

I'm working around this by marking the affected getters as @internal and
adding a test to prevent future regressions.

I believe this is a TypeScript bug, and I filed a bug report:
https://github.com/microsoft/TypeScript/issues/36216

PR Close #34798
2020-01-16 12:06:57 -05:00
Andrew Scott 4d7a9db44c fix(ivy): Ensure ngProjectAs marker name appears at even attribute index (#34617)
The `getProjectAsAttrValue` in `node_selector_matcher` finds the
ProjectAs marker and then additionally checks that the marker appears in
an even index of the node attributes because "attribute names are stored
at even indexes". This is true for "regular" attribute bindings but
classes, styles, bindings, templates, and i18n do not necessarily follow
this rule because there can be an uneven number of them, causing the
next "special" attribute "name" to appear at an odd index. To address
this issue, ensure ngProjectAs is placed right after "regular"
attributes.

PR Close #34617
2020-01-07 10:51:46 -08:00
Andrew Kushnir b4c5bdb093 fix(ivy): append `advance` instructions before `i18nExp` (#34436)
Prior to this commit, there were no `advance` instructions generated before `i18nExp` instructions and as a result, lifecycle hooks for components used inside i18n blocks were flushed too late. This commit adds the logic to generate `advance` instructions in front of `i18nExp` ones (similar to what we have in other places like interpolations, property bindings, etc), so that the necessary lifecycle hooks are flushed before expression value is captured.

PR Close #34436
2020-01-07 10:31:45 -08:00
ayazhafiz 19944c2424 feat(compiler): record end of expression Token (#33549)
In the past, only the starting index of an expression Token has been
recorded, so a parser could demarkate the span of a token only by the
start locations of two tokens. This may lead to trailing whitespace
being included in the token span:

```html
{{ token1   + token2 }}
   ^^^^^^^^^             recorded span of `token1`
```

It's also not enough for a parser to determine the end of a token by
adding the length of the token value to the token's start location,
because lexed expression values may not exactly reflect the source code.
For example, `"d\\"e"` is lexed as a string token whose value is `d"e`.

Instead, this commit adds a `end` field to expression tokens. `end`
is one past the last index of the token source code. This will enable a
parser to determine the span of a token just by looking at that token.

This is a breaking change because the contructor interface of `Token`
has changed.

Part of #33477.

PR Close #33549
2020-01-06 11:00:15 -08:00
JoostK 8c6468a025 refactor(ivy): use absolute source spans in type checker (#34417)
Previously, the type checker would compute an absolute source span by
combining an expression AST node's `ParseSpan` (relative to the start of
the expression) together with the absolute offset of the expression as
represented in a `ParseSourceSpan`, to arrive at a span relative to the
start of the file. This information is now directly available on an
expression AST node in the `AST.sourceSpan` property, which can be used
instead.

PR Close #34417
2019-12-18 14:44:42 -08:00
Pete Bacon Darwin 31be29a9f3 fix(ngcc): use the correct identifiers when updating typings files (#34254)
Previously the identifiers used in the typings files were the same as
those used in the source files.

When the typings files and the source files do not match exactly, e.g.
when one of them is flattened, while the other is a deep tree, it is
possible for identifiers to be renamed.

This commit ensures that the correct identifier is used in typings files
when the typings file does not export the same name as the source file.

Fixes https://github.com/angular/ngcc-validation/pull/608

PR Close #34254
2019-12-18 11:25:01 -08:00
Ayaz Hafiz 3e201181bb fix(ivy): correctly associate output bound events with directives (#31938)
Previously, bound events were incorrectly bound to directives with
inputs matching the bound event attribute. This fixes that so bound
events can only be bound to directives with matching outputs.

Adds tests for all kinds of directive matching on bound attributes.

PR Close #31938
2019-12-17 14:39:33 -08:00
Ayaz Hafiz ddc229b69b fix(ivy): record correct absolute source span for ngForOf expressions (#31813)
Expressions in an inline template binding are improperly recorded as
spaning an offset calculated from the start of the template binding
attribute key, whereas they should be calculated from the start of the
attribute value, which contains the actual binding AST.

PR Close #31813
2019-12-16 08:11:48 -08:00
JoostK ff0a91422a perf(compiler): speed up i18n digest computations (#34332)
Avoids the usage of array destructuring, as it introduces calls to
a `__values` helper function in ES5 that has a relatively high
performance impact. This shaves off roughly 130ms of CPU time for a
large compilation with big templates that uses i18n.

PR Close #34332
2019-12-12 14:06:37 -08:00
JoostK 014a7137f4 perf(compiler): use a shared interpolation regex (#34332)
The template parser has a certain interpolation config associated with
it and builds a regular expression each time it needs to extract the
interpolations from an input string. Since the interpolation config is
typically the default of `{{` and `}}`, the regular expression doesn't
have to be recreated each time. Therefore, this commit creates only a
single regular expression instance that is used for the default
configuration.

In a large compilation unit with big templates, computing the regular
expression took circa 275ms. This change reduces this to effectively
zero.

PR Close #34332
2019-12-12 14:06:37 -08:00
JoostK 4945274080 perf(compiler): optimize cloning cursors state (#34332)
On a large compilation unit with big templates, the total time spent in
the `PlainCharacterCursor` constructor was 470ms. This commit applies
two optimizations to reduce this time:

1. Avoid the object spread operator within the constructor, as the
generated `__assign` helper in the emitted UMD bundle (ES5) does not
optimize well compared to a hardcoded object literal. This results in a
significant performance improvement. Because of the straight-forward
object literal, the VM is now much better able to optimize the memory
allocations which makes a significant difference as the
`PlainCharacterCursor` constructor is called in tight loops.

2. Reduce the number of `CharacterCursor` clones. Although cloning
itself is now much faster because of the optimization above, several
clone operations were not necessary.

Combined, these changes reduce the total time spent in the
`PlainCharacterCursor` constructor to just 10ms.

PR Close #34332
2019-12-12 14:06:37 -08:00
JoostK 6e5f076330 perf(ivy): share instances of `DomElementSchemaRegistry` (#34332)
To create a binding parser, an instance of `ElementSchemaRegistry` is
required. Prior to this change, each time a new binding parser was
created a new instance of `DomElementSchemaRegistry` would be
instantiated. This is an expensive operation that takes roughly 1ms per
instantiation, so it is key that multiple allocations are avoided.

By sharing a single `DomElementSchemaRegistry`, we avoid two such
allocations, i.e. save ~2ms, per component template.

PR Close #34332
2019-12-12 14:06:36 -08:00
JoostK b72c7a89a9 refactor(ivy): include generic type for `ModuleWithProviders` in .d.ts files (#34235)
The `ModuleWithProviders` type has an optional type parameter that
should be specified to indicate what NgModule class will be provided.
This enables the Ivy compiler to statically determine the NgModule type
from the declaration files. This type parameter will become required in
the future, however to aid in the migration the compiler will detect
code patterns where using `ModuleWithProviders` as return type is
appropriate, in which case it transforms the emitted .d.ts files to
include the generic type argument.

This should reduce the number of occurrences where `ModuleWithProviders`
is referenced without its generic type argument.

Resolves FW-389

PR Close #34235
2019-12-10 16:34:47 -08:00
Alex Rickabaugh 13c2fad240 fix(ivy): throw a better error when DI can't inject a ctor param (#33739)
Occasionally a factory function needs to be generated for an "invalid"
constructor (one with parameters types which aren't injectable). Typically
this happens in JIT mode where understanding of parameters cannot be done in
the same "up-front" way that the AOT compiler can.

This commit changes the JIT compiler to generate a new `invalidFactoryDep`
call for each invalid parameter. This instruction will error at runtime if
called, indicating both the index of the invalid parameter as well as (via
the stack trace) the factory function which was generated for the type being
constructed.

Fixes #33637

PR Close #33739
2019-12-09 11:37:10 -08:00
Pete Bacon Darwin a12b5f930a fix(compiler): ensure localized strings are ES5 compatible for JIT mode (#34265)
Previously the JIT evaluated code for ivy localized strings included
backtick tagged template strings, which are not compatible with ES5
in legacy browsers such as IE 11.

Now the generated code is ES5 compatible.

Fixes #34246

PR Close #34265
2019-12-06 13:03:46 -08:00
Pete Bacon Darwin c4ce24647b fix(compiler-cli): ensure that `ngI18nClosureMode` is guarded in generated code (#34211)
If the `ngI18nClosureMode` global check actually makes it
through to the runtime, then checks for its existence should
be guarded to prevent `Reference undefined` errors in strict
mode.

(Normally, it is stripped out by dead code elimination during
build optimization.)

This comment ensures that generated template code guards
this global check.

PR Close #34211
2019-12-03 16:18:12 -08:00
Andrew Kushnir c50faa97ca fix(ivy): correctly support `ngProjectAs` on templates (#34200)
Prior to this commit, if a template (for example, generated using structural directive such as *ngIf) contains `ngProjectAs` attribute, it was not included into attributes array in generated code and as a result, these templates were not matched at runtime during content projection. This commit adds the logic to append `ngProjectAs` values into corresponding element's attribute arrays, so content projection works as expected.

PR Close #34200
2019-12-03 16:12:55 -08:00
Pete Bacon Darwin 6b1a47183d fix(ivy): i18n - trim whitespace when parsing metadata (#34154)
It is possible for HTML formatters to add whitespace
around the content of `i18n` attribute values. This can
make the meaning and custom ids brittle to simple
whitespace formatting.

This commit ensures that the metadata string extracted
from HTML `i18n` attributes is trimmed before being parsed
into meaning, description and custom id.

PR Close #34154
2019-12-03 10:20:53 -08:00
Pete Bacon Darwin 41485599f3 refactor(compiler): remove redundant `metaFromI18nMessage()` function (#34154)
PR Close #34154
2019-12-03 10:20:49 -08:00
Pete Bacon Darwin f6a6f26e0f fix(compiler): i18n - trim whitespace from i18n custom ids (#34154)
Fixes #34147

PR Close #34154
2019-12-03 10:16:56 -08:00