231 Commits

Author SHA1 Message Date
Pawel Kozlowski
87743f1aa1 fix(ivy): descend into view containers on elements when collecting rootNodes ()
PR Close 
2019-10-30 11:46:09 -07:00
Pawel Kozlowski
502fb7e307 fix(ivy): descend into view containers on ng-template when collecting rootNodes ()
PR Close 
2019-10-30 11:46:09 -07:00
Andrew Kushnir
bd40c89688 fix(ivy): handle elements with local refs in i18n blocks ()
Prior to this commit, i18n logic which ensures that elements removed in a translation are also removed in DOM, didn't take into account the fact that elements may have local refs. As a result, remove operation failed, since there is no corresponding tNode found. This commit updates the logic to skip all local refs while going though the list of nodes to ensure that DOM matches elements present in translation.

PR Close 
2019-10-29 11:47:28 -07:00
Miško Hevery
e16f75db56 refactor(ivy): move bindingIndex from LView to LFrame ()
`bindingIndex` stores the current location of the bindings in the
template function. Because it used to be stored in `LView` that `LView`
was not reentrant. This could happen if a binding was a getter and had
a side-effect of calling `detectChanges()`.

By moving the `bindingIndex` to `LFrame` where all of the global state
is kept in reentrant way we correct the issue.

PR Close 
2019-10-28 10:59:29 -07:00
crisbeto
14c4b1b205 refactor(ivy): remove ngBaseDef ()
Removes `ngBaseDef` from the compiler and any runtime code that was still referring to it. In the cases where we'd previously generate a base def we now generate a definition for an abstract directive.

PR Close 
2019-10-25 13:11:34 -07:00
Alex Rickabaugh
818c514968 feat(ivy): add a runtime feature to copy cmp/dir definitions ()
This commit adds CopyDefinitionFeature, which supports the case where an
entire decorator (@Component or @Directive) is inherited from parent to
child.

The existing inheritance feature, InheritDefinitionFeature, supports merging
of parent and child definitions when both were originally present. This
merges things like inputs, outputs, host bindings, etc.

CopyDefinitionFeature, on the other hand, compensates for a definition that
was missing entirely on the child class, by copying fields that aren't
ordinarily inherited (like the template function itself).

This feature is intended to only be used as part of ngcc code generation.

PR Close 
2019-10-25 09:16:50 -07:00
Matias Niemelä
dcdb433b7d perf(ivy): apply [style]/[class] bindings directly to style/className ()
This patch ensures that the `[style]` and `[class]` based bindings
are directly applied to an element's style and className attributes.

This patch optimizes the algorithm so that it...
- Doesn't construct an update an instance of `StylingMapArray` for
  `[style]` and `[class]` bindings
- Doesn't apply `[style]` and `[class]` based entries using
  `classList` and `style` (direct attributes are used instead)
- Doesn't split or iterate over all string-based tokens in a
  string value obtained from a `[class]` binding.

This patch speeds up the following cases:
- `<div [class]>` and `<div class="..." [class]>`
- `<div [style]>` and `<div style="..." [style]>`

The overall speec increase is by over 5x.

PR Close 
2019-10-24 17:42:46 -07:00
Miško Hevery
09a2bb839f refactor(ivy): Intruduce LFrame to store global instruction information ()
`LFrame` stores information specifice to the current `LView` As the code
enters and leaves `LView`s we use `enterView()` and `leaveView()`
respectively to build a a stack of `LFrame`s. This allows us to easily
restore the previous `LView` instruction state.

PR Close 
2019-10-24 14:42:15 -07:00
Miško Hevery
5632424d04 refactor(ivy): ViewRef needs embededViewRef declaration ()
PR Close 
2019-10-22 12:00:21 -07:00
Matias Niemelä
7b64680670 fix(ivy): ensure map-based interpolation works with other map-based sources ()
Prior to this fix if a map-based class or style binding wrote
its values onto an elemenent, the internal styling context would
not register the binding if the initial value as a `NO_CHANGE`
value. This situation occurs if a directive takes control of the
`class` or `style` input values and then returns a `NO_CHANGE` value
if the initial value is empty.

This patch ensures that all bindings are always registered with the
`TStylingContext` data-structure even if their initial value is
an instance of `NO_CHANGE`.

PR Close 
2019-10-17 18:24:10 -04:00
Matias Niemelä
f45c43188f fix(ivy): ensure errors are thrown during checkNoChanges for style/class bindings ()
Prior to this fix, all style/class bindings (e.g. `[style]` and
`[class.foo]`) would quietly update a binding value if and when the
current binding value changes during checkNoChanges.

With this patch, all styling instructions will properly check to see
if the value has changed during the second pass of detectChanges()
if checkNoChanges is active.

PR Close 
2019-10-17 16:46:49 -04:00
crisbeto
9d54679e66 test: clean up explicit dynamic query usages ()
Cleans up all the places where we explicitly set `static: false` on queries.

PR Close 
2019-10-17 16:10:10 -04:00
Andrew Kushnir
7e64bbe5a8 fix(ivy): use container i18n meta if a message is a single ICU ()
Prior to this commit, metadata defined on ICU container element was not inherited by the ICU if the whole message is a single ICU (for example: `<ng-container i18n="meaning|description@@id">{count, select, ...}</ng-container>). This commit updates the logic to use parent container i18n meta information for the cases when a message consists of a single ICU.

Fixes 

PR Close 
2019-10-17 16:07:07 -04:00
Andrew Kushnir
6f203c9575 fix(ivy): handling className as an input properly ()
Prior to this commit, all `className` inputs were not set because the runtime code assumed that the `classMap` instruction is only generated for `[class]` bindings. However the `[className]` binding also produces the same `classMap`, thus the code needs to distinguish between `class` and `className`. This commit adds extra logic to select the right input name and also throws an error in case `[class]` and `[className]` bindings are used on the same element simultaneously.

PR Close 
2019-10-17 14:16:02 -04:00
Andrew Kushnir
11e04b1892 fix(ivy): avoid DOM element assertions if procedural renderer is used ()
Prior to this commit, Ivy runtime asserted that a given element is an instance of a DOM node. These asserts may not be correct in case custom renderer is used, which operates objects with a shape different than DOM nodes. This commit updates the code to avoid the mentioned checks in case procedural renderer is used.

PR Close 
2019-10-15 21:03:29 +00:00
Matias Niemelä
1cda80eb3a fix(ivy): ensure sanitizer is not used when direct class application occurs ()
Prior to this patch, if a map-class binding is applied directly then
that value will be incorrectly provided a sanitizer even if there is no
sanitization present for an element.

PR Close 
2019-10-15 16:50:43 +00:00
Matias Niemelä
35a95a8a7e refactor(ivy): ensure StylingDebug instances provide context debug info ()
This patch enables a styling debug instance (which is apart of the
`debugNode.styles` or `debugNode.classes` data structures) to expose
its context value so that it can be easily debugged.

PR Close 
2019-10-10 13:59:32 -07:00
Kristiyan Kostadinov
3efb060127 fix(ivy): unable to bind style zero ()
Fixes not being able to bind zero as a value in style bindings.

Fixes .

PR Close 
2019-10-07 11:00:19 -07:00
Andrew Kushnir
90fb5d9f7a fix(ivy): generate ng-reflect properties for i18n attributes ()
Prior to this change, ng-reflect properties were not created in case an attribute was marked as translatable (for ex. `i18n-title`). This commit adds the logic to generate ng-reflect for such cases.

PR Close 
2019-10-07 10:50:44 -07:00
Pawel Kozlowski
60047037a3 perf(ivy): attempt rendering initial styling only if present ()
PR Close 
2019-10-04 11:44:57 -07:00
Pete Bacon Darwin
9188751adc fix(ivy): i18n - do not render message ids unnecessarily ()
In an attempt to be compatible with previous translation files
the Angular compiler was generating instructions that always
included the message id. This was because it was not possible
to accurately re-generate the id from the calls to `$localize()` alone.

In line with https://hackmd.io/EQF4_-atSXK4XWg8eAha2g this
commit changes the compiler so that it only renders ids if they are
"custom" ones provided by the template author.

NOTE:

When translating messages generated by the Angular compiler
from i18n tags in templates, the `$localize.translate()` function
will compute message ids, if no custom id is provided, using a
common digest function that only relies upon the information
available in the `$localize()` calls.

This computed message id will not be the same as the message
ids stored in legacy translation files. Such files will need to be
migrated to use the new common digest function.

This only affects developers who have been trialling `$localize`, have
been calling `loadTranslations()`, and are not exclusively using custom
ids in their templates.

PR Close 
2019-10-02 14:52:00 -07:00
crisbeto
4e35e348af refactor(ivy): generate ngFactoryDef for injectables ()
With  we moved the factories for components, directives and pipes into a new field called `ngFactoryDef`, however I decided not to do it for injectables, because they needed some extra logic. These changes set up the `ngFactoryDef` for injectables as well.

For reference, the extra logic mentioned above is that for injectables we have two code paths:

1. For injectables that don't configure how they should be instantiated, we create a `factory` that proxies to `ngFactoryDef`:

```
// Source
@Injectable()
class Service {}

// Output
class Service {
  static ngInjectableDef = defineInjectable({
    factory: () => Service.ngFactoryFn(),
  });

  static ngFactoryFn: (t) => new (t || Service)();
}
```

2. For injectables that do configure how they're created, we keep the `ngFactoryDef` and generate the factory based on the metadata:

```
// Source
@Injectable({
  useValue: DEFAULT_IMPL,
})
class Service {}

// Output
export class Service {
  static ngInjectableDef = defineInjectable({
    factory: () => DEFAULT_IMPL,
  });

  static ngFactoryFn: (t) => new (t || Service)();
}
```

PR Close 
2019-10-02 13:04:26 -07:00
Andrew Scott
72f3747d7b fix(ivy): refresh child components before executing ViewQuery function ()
Child component refresh must happen before executing the ViewQueryFn because
child components could insert a template from the host that contains the result
of the ViewQuery function (see related test added in this PR).

PR Close 
2019-10-01 14:47:15 -07:00
Matias Niemelä
c32b2ae0a8 fix(ivy): ensure class/style values are debuggable through DebugElement ()
This patch changes the Ivy `DebugElement` code to always read style and
class values directly from the native element instead of reading them
through the styling contexts. The reason for this change is because Ivy
does not make use of a debug renderer and will therefore not have access
to any classes/styles applied directly through the renderer (unless it
reads the values directly from the element).

PR Close 
2019-09-30 14:14:00 -07:00
Andrew Kushnir
966c2a326a fix(ivy): include ngProjectAs into attributes array ()
Prior to this commit, the `ngProjectAs` attribute was only included with a special flag and in a parsed format. As a result, projected node was missing `ngProjectAs` attribute as well as other attributes added after `ngProjectAs` one. This is problematic since app code might rely on the presence of `ngProjectAs` attribute (for example in CSS). This commit fixes the problem by including `ngProjectAs` into attributes array as a regular attribute and also makes sure that the parsed version of the `ngProjectAs` attribute with a special marker is added after regular attributes (thus we set them correctly at runtime). This change also aligns View Engine and Ivy behavior.

PR Close 
2019-09-27 10:12:18 -07:00
Matias Niemelä
a54adcaff0 test(ivy): remove extra implementation of getDebugNode ()
PR Close 
2019-09-25 11:27:33 -07:00
Matias Niemelä
948714c17c revert: refactor(ivy): ensure StylingDebug instances provide context debug info () ()
This reverts commit f8f7c1540a3b667a85887b881a456070b285cb6e.

PR Close 
2019-09-24 16:57:58 -07:00
Matias Niemelä
86fd5719b5 fix(ivy): ensure multiple map-based bindings do not skip intermediate values ()
This patch fixes a bug where the map-based cursor moves too far and
skips intermediate values when the correct combination of single-prop
bindings and map-based bindings are used together.

PR Close 
2019-09-24 11:58:52 -07:00
Matias Niemelä
f8f7c1540a refactor(ivy): ensure StylingDebug instances provide context debug info ()
This patch enables a styling debug instance (which is apart of the
`debugNode.styles` or `debugNode.classes` data structures) to expose
its context value so that it can be easily debugged.

PR Close 
2019-09-24 10:37:42 -07:00
Matias Niemelä
5651fa3a95 fix(ivy): ensure window.ng.getDebugNode returns debug info for component elements ()
Prior to this patch the `window.ng.getDebugNode` method would fail to
return the debug information for an element that is a host element to
a component.

PR Close 
2019-09-23 14:32:42 -07:00
Matias Niemelä
0618bed83e refactor(ivy): combine styling testing files into one ()
PR Close 
2019-09-18 15:06:38 -07:00
Matias Niemelä
4726ac2481 feat(ivy): expose window.ng.getDebugNode helper ()
PR Close 
2019-09-17 15:46:07 -07:00
Pete Bacon Darwin
b741a1c3e7 fix(ivy): i18n - update the compiler to output MessageIds ()
Now that the `$localize` translations are `MessageId` based the
compiler must render `MessageId`s in its generated `$localize` code.
This is because the `MessageId` used by the compiler is computed
from information that does not get passed through to the `$localize`
tagged string.

For example, the generated code for the following template

```html
<div id="static" i18n-title="m|d" title="introduction"></div>
```

will contain these localization statements

```ts
if (ngI18nClosureMode) {
  /**
    * @desc d
    * @meaning m
    */
  const MSG_EXTERNAL_8809028065680254561$$APP_SPEC_TS_1 = goog.getMsg("introduction");
  I18N_1 = MSG_EXTERNAL_8809028065680254561$$APP_SPEC_TS_1;
}
else {
  I18N_1 = $localize \`:m|d@@8809028065680254561:introduction\`;
}
```

Since `$localize` is not able to accurately regenerate the source-message
(and so the `MessageId`) from the generated code, it must rely upon the
`MessageId` being provided explicitly in the generated code.

The compiler now prepends all localized messages with a "metadata block"
containing the id (and the meaning and description if defined).

Note that this metadata block will also allow translation file extraction
from the compiled code - rather than relying on the legacy ViewEngine
extraction code. (This will be implemented post-v9).

Although these metadata blocks add to the initial code size, compile-time
inlining will completely remove these strings and so will not impact on
production bundle size.

PR Close 
2019-09-17 09:17:45 -07:00
Matias Niemelä
a2e890e4f7 refactor(ivy): get rid of styling cleanup functions outside of styling code ()
Prior to this patch, each time `advance()` would run (or when a
templateFn or hostBindings code exits) then the core change detection
code would check to see whether the styling data needs to be reset. This
patch removes that functionality and places everything inside of the
scheduled styling exit function. This means that each time one or more
styling bindings run (even if the value hasn't changed) then an exit
function will be scheduled and that will do all the cleanup.

PR Close 
2019-09-16 14:12:48 -07:00
Matias Niemelä
4f41473048 refactor(ivy): remove styling state storage and introduce direct style writing ()
This patch is a final major refactor in styling Angular.

This PR includes three main fixes:

All temporary state taht is persisted between template style/class application
and style/class application in host bindings is now removed.
Removes the styling() and stylingApply() instructions.
Introduces a "direct apply" mode that is used apply prop-based
style/class in the event that there are no map-based bindings as
well as property collisions.

PR Close 

PR Close 
2019-09-16 14:12:48 -07:00
Andrew Kushnir
5328bb223a fix(ivy): avoid unnecessary i18n instructions generation for <ng-template> with structural directives ()
If an <ng-template> contains a structural directive (for example *ngIf), Ngtsc generates extra template function with 1 template instruction call. When <ng-template> tag also contains i18n attribute on it, we generate i18nStart and i18nEnd instructions around it, which is unnecessary and breaking runtime. This commit adds a logic to make sure we do not generate i18n instructions in case only `template` is present.

PR Close 
2019-09-13 10:01:55 -07:00
Pete Bacon Darwin
2bf5606bbe feat(ivy): i18n - reorganize entry-points for better reuse ()
This is a refactoring that moves the source code around to provide a better
platform for adding the compile-time inlining.

1. Move the global side-effect import from the primary entry-point to a
   secondary entry-point @angular/localize/init.

   This has two benefits: first it allows the top level entry-point to
   contain tree-shakable shareable code; second it gives the side-effect
   import more of an "action" oriented name, which indicates that importing
   it does something tangible

2. Move all the source code into the top src folder, and import the localize
   related functions into the localize/init/index.ts entry-point.

   This allows the different parts of the package to share code without
   a proliferation of secondary entry-points (i.e. localize/utils).

3. Avoid publicly exporting any utilities at this time - the only public
   API at this point are the global `$localize` function and the two runtime
   helpers `loadTranslations()` and `clearTranslations()`.
   This does not mean that we will not expose additional helpers for 3rd
   party tooling in the future, but it avoid us preemptively exposing
   something that we might want to change in the near future.

Notes:

It is not possible to have the `$localize` code in the same Bazel package
as the rest of the code. If we did this, then the bundled `@angular/localize/init`
entry-point code contains all of the helper code, even though most of it is not used.

Equally it is not possible to have the `$localize` types (i.e. `LocalizeFn`
and `TranslateFn`) defined in the `@angular/localize/init` entry-point because
these types are needed for the runtime code, which is inside the primary
entry-point. Importing them from `@angular/localize/init` would run the
side-effect.

The solution is to have a Bazel sub-package at `//packages/localize/src/localize`
which contains these types and the `$localize` function implementation.
The primary `//packages/localize` entry-point imports the types without
any side-effect.
The secondary `//packages/localize/init` entry-point imports the `$localize`
function and attaches it to the global scope as a side-effect, without
bringing with it all the other utility functions.

BREAKING CHANGES:

The entry-points have changed:

* To attach the `$localize` function to the global scope import from
`@angular/localize/init`. Previously it was `@angular/localize`.

* To access the `loadTranslations()` and `clearTranslations()` functions,
import from `@angular/localize`. Previously it was `@angular/localize/run_time`.

PR Close 
2019-09-12 15:35:34 -07:00
cexbrayat
88c28ce208 refactor(ivy): migrate debug spec from render3 ()
Migrate the remaining `render3/debug_spec.ts` to `acceptance`

PR Close 
2019-09-12 11:35:49 -07:00
Matias Niemelä
53dbff66d7 revert: refactor(ivy): remove styling state storage and introduce direct style writing ()
This reverts commit 15aeab16207fd6491e296db02501a14f92ff8e97.
2019-09-11 15:24:10 -07:00
Matias Niemelä
15aeab1620 refactor(ivy): remove styling state storage and introduce direct style writing () ()
This patch is a final major refactor in styling Angular.

This PR includes three main fixes:

All temporary state taht is persisted between template style/class application
and style/class application in host bindings is now removed.
Removes the styling() and stylingApply() instructions.
Introduces a "direct apply" mode that is used apply prop-based
style/class in the event that there are no map-based bindings as
well as property collisions.

PR Close 

PR Close 
2019-09-11 16:27:10 -04:00
Matias Niemelä
c84c27f7f4 revert: refactor(ivy): remove styling state storage and introduce direct style writing () 2019-09-10 18:08:05 -04:00
Matias Niemelä
3b37469735 refactor(ivy): remove styling state storage and introduce direct style writing ()
This patch is a final major refactor in styling Angular.

This PR includes three main fixes:

All temporary state taht is persisted between template style/class application
and style/class application in host bindings is now removed.
Removes the styling() and stylingApply() instructions.
Introduces a "direct apply" mode that is used apply prop-based
style/class in the event that there are no map-based bindings as
well as property collisions.

PR Close 
2019-09-10 15:54:58 -04:00
cexbrayat
f00bb85b58 refactor(ivy): migrate content spec from render3 ()
Migrate the remaining `render3/content_spec.ts` to `acceptance` (some JS block ones were already migrated with `ngIf`).

PR Close 
2019-09-10 13:03:16 -04:00
cexbrayat
8a6e54a06d test(ivy): test case-insensitive selectors ()
Adds two acceptance tests to show a current difference in behavior between Ivy and VE.
A directive with a selector `.Titledir` matches an element with `class="titleDir"` in VE but not in Ivy.
Same thing for an attribute value.

PR Close 
2019-09-10 06:31:22 -04:00
Andrew Kushnir
a1beba4b6e fix(ivy): restore global state after running refreshView ()
Prior to this commit, the `previousOrParentTNode` was set to null after performing all operations within `refreshView` function. It's causing problems in more complex scenarios, for example when change detection is triggered during DI (see test added as a part of this commit). As a result, global state might be corrupted. This commit captures current value of `previousOrParentTNode` and restores it after `refreshView` call.

PR Close 
2019-09-10 06:30:49 -04:00
Pete Bacon Darwin
ea6a2e9f25 fix(ivy): template compiler should render correct $localize placeholder names ()
The `goog.getMsg()` function requires placeholder names to be camelCased.

This is not the case for `$localize`. Here placeholder names need
match what is serialized to translation files.

Specifically such placeholder names keep their casing but have all characters
that are not in `a-z`, `A-Z`, `0-9` and `_` converted to `_`.

PR Close 
2019-09-09 19:11:36 -04:00
Carlos Ortiz García
9166baf709 refactor(core): Migrate TestBed.get to TestBed.inject ()
This is cleanup/followup for PR 

PR Close 
2019-09-09 19:10:54 -04:00
crisbeto
bc061b78be fix(ivy): warn instead of throwing for unknown properties ()
Logs a warning instead of throwing when running into a binding to an unknown property in JIT mode. Since we aren't using a schema for the runtime validation anymore, this allows us to support browsers where properties are unsupported.

PR Close 
2019-09-06 13:15:03 -04:00
crisbeto
62d92f8091 fix(ivy): unable to bind to properties that start with class or style ()
Fixes Ivy picking up property bindings that start with `class` or `style` as if they're style bindings.

Fixes 

PR Close 
2019-09-05 18:10:08 -04:00
Andrew Kushnir
098feec4a0 fix(ivy): maintain coalesced listeners order ()
Prior to this commit, listeners order was not preserved in case we coalesce them to avoid triggering unnecessary change detection cycles. For performance reasons we were attaching listeners to existing events at head (always using first listener as an anchor), to avoid going through the list, thus breaking the order in which listeners are registered. In some scenarios this order might be important (for example with `ngModelChange` and `input` listeners), so this commit updates the logic to put new listeners at the end of the list. In order to avoid performance implications, we keep a pointer to the last listener in the list, so adding a new listener takes constant amount of time.

PR Close 
2019-09-05 18:09:47 -04:00