Commit Graph

48 Commits

Author SHA1 Message Date
Alex Rickabaugh 08a4f10ee7 fix(ivy): move setClassMetadata calls into a pure iife (#33337)
This commit transforms the setClassMetadata calls generated by ngtsc from:

```typescript
/*@__PURE__*/ setClassMetadata(...);
```

to:

```typescript
/*@__PURE__*/ (function() {
  setClassMetadata(...);
})();
```

Without the IIFE, terser won't remove these function calls because the
function calls have arguments that themselves are function calls or other
impure expressions. In order to make the whole block be DCE-ed by terser,
we wrap it into IIFE and mark the IIFE as pure.

It should be noted that this change doesn't have any impact on CLI* with
build-optimizer, which removes the whole setClassMetadata block within
the webpack loader, so terser or webpack itself don't get to see it at
all. This is done to prevent cross-chunk retention issues caused by
webpack's internal module registry.

* actually we do expect a short-term size regression while
https://github.com/angular/angular-cli/pull/16228
is merged and released in the next rc of the CLI. But long term this
change does nothing to CLI + build-optimizer configuration and is done
primarly to correct the seemingly correct but non-function PURE annotation
that builds not using build-optimizer could rely on.

PR Close #33337
2019-11-20 12:55:58 -08:00
George Kalpakas 033aba9351 fix(ngcc): do not emit ES2015 code in ES5 files (#33514)
Previously, ngcc's `Renderer` would add some constants in the processed
files which were emitted as ES2015 code (e.g. `const` declarations).
This would result in invalid ES5 generated code that would break when
run on browsers that do not support the emitted format.

This commit fixes it by adding a `printStatement()` method to
`RenderingFormatter`, which can convert statements to JavaScript code in
a suitable format for the corresponding `RenderingFormatter`.
Additionally, the `translateExpression()` and `translateStatement()`
ngtsc helper methods are augmented to accept an extra hint to know
whether the code needs to be translated to ES5 format or not.

Fixes #32665

PR Close #33514
2019-11-13 13:49:31 -08:00
George Kalpakas 704775168d fix(ngcc): generate correct metadata for classes with getter/setter properties (#33514)
While processing class metadata, ngtsc generates a `setClassMetadata()`
call which (among other things) contains info about property decorators.
Previously, processing getter/setter pairs with some of ngcc's
`ReflectionHost`s resulted in multiple metadata entries for the same
property, which resulted in duplicate object keys, which in turn causes
an error in ES5 strict mode.

This commit fixes it by ensuring that there are no duplicate property
names in the `setClassMetadata()` calls.

In addition, `generateSetClassMetadataCall()` is updated to treat
`ClassMember#decorators: []` the same as `ClassMember.decorators: null`
(i.e. omitting the `ClassMember` from the generated `setClassMetadata()`
call). Alternatively, ngcc's `ReflectionHost`s could be updated to do
this transformation (`decorators: []` --> `decorators: null`) when
reflecting on class members, but this would require changes in many
places and be less future-proof.

For example, given a class such as:

```ts
class Foo {
  @Input() get bar() { return 'bar'; }
  set bar(value: any) {}
}
```

...previously the generated `setClassMetadata()` call would look like:

```ts
ɵsetClassMetadata(..., {
  bar: [{type: Input}],
  bar: [],
});
```

The same class will now result in a call like:

```ts
ɵsetClassMetadata(..., {
  bar: [{type: Input}],
});
```

Fixes #30569

PR Close #33514
2019-11-13 13:49:31 -08:00
Pete Bacon Darwin fe12d0dc78 fix(ngcc): render adjacent statements after static properties (#33630)
See https://github.com/angular/angular/pull/33337#issuecomment-545487737

Fixes FW-1664

PR Close #33630
2019-11-06 19:54:05 +00:00
Pete Bacon Darwin 85298e345d fix(ngcc): render new definitions using the inner name of the class (#33533)
When decorating classes with ivy definitions (e.g. `ɵfac` or `ɵdir`)
the inner name of the class declaration must be used.

This is because in ES5 the definitions are inside the class's IIFE
where the outer declaration has not yet been initialized.

PR Close #33533
2019-11-05 17:25:02 +00:00
crisbeto c3e93564d0 perf(ivy): avoid generating selectors array for directives without a selector (#33431)
Now that we've replaced `ngBaseDef` with an abstract directive definition, there are a lot more cases where we generate a directive definition without a selector. These changes make it so that we don't generate the `selectors` array if it's going to be empty.

PR Close #33431
2019-10-29 12:06:15 -07:00
crisbeto 14c4b1b205 refactor(ivy): remove ngBaseDef (#33264)
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 #33264
2019-10-25 13:11:34 -07:00
Alex Rickabaugh e030375d9a feat(ngcc): enable private NgModule re-exports in ngcc on request (#33177)
This commit adapts the private NgModule re-export system (using aliasing) to
ngcc. Not all ngcc compilations are compatible with these re-exports, as
they assume a 1:1 correspondence between .js and .d.ts files. The primary
concern here is supporting them for commonjs-only packages.

PR Close #33177
2019-10-22 13:14:31 -04:00
Kara Erickson cda9248b33 refactor(core): rename ngInjectorDef to ɵinj (#33151)
Injector defs are not considered public API, so the property
that contains them should be prefixed with Angular's marker
for "private" ('ɵ') to discourage apps from relying on def
APIs directly.

This commit adds the prefix and shortens the name from
ngInjectorDef to inj. This is because property names
cannot be minified by Uglify without turning on property
mangling (which most apps have turned off) and are thus
size-sensitive.

PR Close #33151
2019-10-16 16:36:19 -04:00
Kara Erickson fc93dafab1 refactor(core): rename ngModuleDef to ɵmod (#33142)
Module defs are not considered public API, so the property
that contains them should be prefixed with Angular's marker
for "private" ('ɵ') to discourage apps from relying on def
APIs directly.

This commit adds the prefix and shortens the name from
ngModuleDef to mod. This is because property names
cannot be minified by Uglify without turning on property
mangling (which most apps have turned off) and are thus
size-sensitive.

PR Close #33142
2019-10-14 23:08:10 +00:00
Kara Erickson 0de2a5e408 refactor(core): rename ngFactoryDef to ɵfac (#33116)
Factory defs are not considered public API, so the property
that contains them should be prefixed with Angular's marker
for "private" ('ɵ') to discourage apps from relying on def
APIs directly.

This commit adds the prefix and shortens the name from
ngFactoryDef to fac. This is because property names
cannot be minified by Uglify without turning on property
mangling (which most apps have turned off) and are thus
size-sensitive.

Note that the other "defs" (ngPipeDef, etc) will be
prefixed and shortened in follow-up PRs, in an attempt to
limit how large and conflict-y this change is.

PR Close #33116
2019-10-14 20:27:25 +00:00
Kara Erickson 1a67d70bf8 refactor(core): rename ngDirectiveDef to ɵdir (#33110)
Directive defs are not considered public API, so the property
that contains them should be prefixed with Angular's marker
for "private" ('ɵ') to discourage apps from relying on def
APIs directly.

This commit adds the prefix and shortens the name from
ngDirectiveDef to dir. This is because property names
cannot be minified by Uglify without turning on property
mangling (which most apps have turned off) and are thus
size-sensitive.

Note that the other "defs" (ngFactoryDef, etc) will be
prefixed and shortened in follow-up PRs, in an attempt to
limit how large and conflict-y this change is.

PR Close #33110
2019-10-14 16:20:11 +00:00
Kara Erickson 64fd0d6db9 refactor(core): rename ngComponentDef to ɵcmp (#33088)
Component defs are not considered public API, so the property
that contains them should be prefixed with Angular's marker
for "private" ('ɵ') to discourage apps from relying on def
APIs directly.

This commit adds the prefix and shortens the name from
`ngComponentDef` to `cmp`. This is because property names
cannot be minified by Uglify without turning on property
mangling (which most apps have turned off) and are thus
size-sensitive.

Note that the other "defs" (ngDirectiveDef, etc) will be
prefixed and shortened in follow-up PRs, in an attempt to
limit how large and conflict-y this change is.

PR Close #33088
2019-10-11 15:45:22 -07:00
crisbeto d5b87d32b0 perf(ivy): move attributes array into component def (#32798)
Currently Ivy stores the element attributes into an array above the component def and passes it into the relevant instructions, however the problem is that upon minification the array will get a unique name which won't compress very well. These changes move the attributes array into the component def and pass in the index into the instructions instead.

Before:
```
const _c0 = ['foo', 'bar'];

SomeComp.ngComponentDef = defineComponent({
  template: function() {
    element(0, 'div', _c0);
  }
});
```

After:
```
SomeComp.ngComponentDef = defineComponent({
  consts: [['foo', 'bar']],
  template: function() {
    element(0, 'div', 0);
  }
});
```

A couple of cases that this PR doesn't handle:
* Template references are still in a separate array.
* i18n attributes are still in a separate array.

PR Close #32798
2019-10-09 13:16:55 -07:00
Kristiyan Kostadinov c885178d5f refactor(ivy): move directive, component and pipe factories to ngFactoryFn (#31953)
Reworks the compiler to output the factories for directives, components and pipes under a new static field called `ngFactoryFn`, instead of the usual `factory` property in their respective defs. This should eventually allow us to inject any kind of decorated class (e.g. a pipe).

**Note:** these changes are the first part of the refactor and they don't include injectables. I decided to leave injectables for a follow-up PR, because there's some more cases we need to handle when it comes to their factories. Furthermore, directives, components and pipes make up most of the compiler output tests that need to be refactored and it'll make follow-up PRs easier to review if the tests are cleaned up now.

This is part of the larger refactor for FW-1468.

PR Close #31953
2019-08-27 13:57:00 -07:00
Kristiyan Kostadinov 4ea3e7e000 refactor(ivy): combine query load instructions (#32100)
Combines the `loadViewQuery` and `loadContentQuery` instructions since they have the exact same internal logic. Based on a discussion here: https://github.com/angular/angular/pull/32067#pullrequestreview-273001730

PR Close #32100
2019-08-12 10:32:08 -07:00
George Kalpakas ed70f73794 refactor(ivy): ngcc - remove `formatProperty` from `EntryPointBundle` (#32052)
Remove the `formatProperty` property from the `EntryPointBundle`
interface, because the property is not directly related to that type.

It was only used in one place, when calling `fileWriter.writeBundle()`,
but we can pass `formatProperty` directrly to `writeBundle()`.

PR Close #32052
2019-08-08 11:14:38 -07:00
Alex Rickabaugh f2d47c96c4 fix(ivy): ngcc emits static fields before extra statements (#31933)
This commit changes the emit order of ngcc when a class has multiple static
fields being assigned. Previously, ngcc would emit each static field
followed immediately by any extra statements specified for that field. This
causes issues with downstream tooling such as build optimizer, which expects
all of the static fields for a class to be grouped together. ngtsc already
groups static fields and additional statements. This commit changes ngcc's
ordering to match.

PR Close #31933
2019-08-01 10:45:36 -07:00
crisbeto 3d7303efc0 perf(ivy): avoid extra parameter in query instructions (#31667)
Currently we always generate the `read` parameter for the view and content query instructions, however since most of the time the `read` parameter won't be set, we'll end up generating `null` which adds 5 bytes for each query when minified. These changes make it so that the `read` parameter only gets generated if it has a value.

PR Close #31667
2019-07-24 14:37:51 -07:00
Pete Bacon Darwin d39a2beae1 refactor(ivy): ngcc - move decorator analysis types into their own file (#31544)
PR Close #31544
2019-07-23 21:11:39 -07:00
Pete Bacon Darwin f690a4e0af fix(ivy): ngcc - do not analyze files outside the current package (#30591)
Our module resolution prefers `.js` files over `.d.ts` files because
occasionally libraries publish their typings in the same directory
structure as the compiled JS files, i.e. adjacent to each other.

The standard TS module resolution would pick up the typings
file and add that to the `ts.Program` and so they would be
ignored by our analyzers. But we need those JS files, if they
are part of the current package.

But this meant that we also bring in JS files from external
imports from outside the package, which is not desired.
This was happening for the `@fire/storage` enty-point
that was importing the `firebase/storage` path.

In this commit we solve this problem, for the case of imports
coming from a completely different package, by saying that any
file that is outside the package root directory must be an external
import and so we do not analyze those files.

This does not solve the potential problem of imports between
secondary entry-points within a package but so far that does
not appear to be a problem.

PR Close #30591
2019-06-26 08:00:03 -07:00
Pete Bacon Darwin 42036f4b79 refactor(ivy): ngcc - pass `bundle` to `DecorationAnalyzer` (#30591)
Rather than passing a number of individual arguments, we can
just pass an `EntryPointBundle`, which already contains them.

This is also a precursor to using more of the properties in the bundle.

PR Close #30591
2019-06-26 08:00:03 -07:00
Pete Bacon Darwin 74f637f98d refactor(ivy): ngcc - no need to pass `isCore` explicitly (#30591)
It is part of `EntryPointBundle` so we can just use that, which
is generally already passed around.

PR Close #30591
2019-06-26 08:00:03 -07:00
Pete Bacon Darwin e943859843 refactor(ivy): ngcc - expose the `entryPoint` from the `EntryPointBundle` interface (#30591)
This will allow users of the `EntryPointBundle` to use some of the `EntryPoint`
properties without us having to pass them around one by one.

PR Close #30591
2019-06-26 08:00:03 -07:00
Pete Bacon Darwin 7186f9c016 refactor(ivy): implement a virtual file-system layer in ngtsc + ngcc (#30921)
To improve cross platform support, all file access (and path manipulation)
is now done through a well known interface (`FileSystem`).

For testing a number of `MockFileSystem` implementations are provided.
These provide an in-memory file-system which emulates operating systems
like OS/X, Unix and Windows.

The current file system is always available via the static method,
`FileSystem.getFileSystem()`. This is also used by a number of static
methods on `AbsoluteFsPath` and `PathSegment`, to avoid having to pass
`FileSystem` objects around all the time. The result of this is that one
must be careful to ensure that the file-system has been initialized before
using any of these static methods. To prevent this happening accidentally
the current file system always starts out as an instance of `InvalidFileSystem`,
which will throw an error if any of its methods are called.

You can set the current file-system by calling `FileSystem.setFileSystem()`.
During testing you can call the helper function `initMockFileSystem(os)`
which takes a string name of the OS to emulate, and will also monkey-patch
aspects of the TypeScript library to ensure that TS is also using the
current file-system.

Finally there is the `NgtscCompilerHost` to be used for any TypeScript
compilation, which uses a given file-system.

All tests that interact with the file-system should be tested against each
of the mock file-systems. A series of helpers have been provided to support
such tests:

* `runInEachFileSystem()` - wrap your tests in this helper to run all the
wrapped tests in each of the mock file-systems.
* `addTestFilesToFileSystem()` - use this to add files and their contents
to the mock file system for testing.
* `loadTestFilesFromDisk()` - use this to load a mirror image of files on
disk into the in-memory mock file-system.
* `loadFakeCore()` - use this to load a fake version of `@angular/core`
into the mock file-system.

All ngcc and ngtsc source and tests now use this virtual file-system setup.

PR Close #30921
2019-06-25 16:25:24 -07:00
Paul Gschwendtner 2b4d5c7548 fix(ivy): ngcc should process undecorated base classes (#30821)
Currently undecorated classes are intentionally not processed
with ngcc. This is causing unexpected behavior because decorator
handlers such as `base_def.ts` are specifically interested in class
definitions without top-level decorators, so that the base definition
can be generated if there are Angular-specific class members.

In order to ensure that undecorated base-classes work as expected
with Ivy, we need to run the decorator handlers for all top-level
class declarations (not only for those with decorators). This is similar
to when `ngtsc` runs decorator handlers when analyzing source-files.

Resolves FW-1355. Fixes https://github.com/angular/components/issues/16178

PR Close #30821
2019-06-11 00:19:34 +00:00
Ben Lesh c0386757b1 refactor(ivy): inherently call ɵɵselect(0) (#30830)
- Refactors compiler to stop generating `ɵɵselect(0)` instructions
- Alters template execution to always call the equivalent of `ɵɵselect(0)` before running a template in update mode
- Updates tests to not check for or call `ɵɵselect(0)`.

The goal here is to reduce the size of generated templates

PR Close #30830
2019-06-07 08:48:31 -07:00
Ben Lesh dd0815095f feat(ivy): add ɵɵtextInterpolateX instructions (#30011)
- `ɵɵtextBinding(..., ɵɵinterpolationX())` instructions will now just be `ɵɵtextInterpolate(...)` instructions

PR Close #30011
2019-05-29 12:38:58 -04:00
Ben Lesh d7eaae6f22 refactor(ivy): Move instructions back to ɵɵ (#30546)
There is an encoding issue with using delta `Δ`, where the browser will attempt to detect the file encoding if the character set is not explicitly declared on a `<script/>` tag, and Chrome will find the `Δ` character and decide it is window-1252 encoding, which misinterprets the `Δ` character to be some other character that is not a valid JS identifier character

So back to the frog eyes we go.

```
    __
   /ɵɵ\
  ( -- ) - I am ineffable. I am forever.
 _/    \_
/  \  /  \
==  ==  ==
```

PR Close #30546
2019-05-20 16:37:47 -07:00
Pete Bacon Darwin c613596658 fix(ivy): ngcc - separate typings rendering from src rendering (#25445)
Previously the same `Renderer` was used to render typings (.d.ts)
files. But the new `UmdRenderer` is not able to render typings files
correctly.

This commit splits out the typings rendering from the src rendering.
To achieve this the previous renderers have been refactored from
sub-classes of the abstract `Renderer` class to  classes that implement
the `RenderingFormatter` interface, which are then passed to the
`Renderer` and `DtsRenderer` to modify its rendering behaviour.

Along the way a few utility interfaces and classes have been moved
around and renamed for clarity.

PR Close #25445
2019-05-16 12:11:04 -07:00
Pete Bacon Darwin f6aa60c03c feat(ivy): ngcc - implement `UmdRenderer` (#25445)
PR Close #25445
2019-05-16 12:11:04 -07:00
Pete Bacon Darwin 95c5b1a7f6 refactor(ivy): use a named type for ImportManager import structures (#25445)
Previously we were using an anonymous type `{specifier: string; qualifier: string;}`
throughout the code base. This commit gives this type a name and ensures it
is only defined in one place.

PR Close #25445
2019-05-16 12:11:03 -07:00
Pete Bacon Darwin 8e201f713a test(ivy): ngcc - check the actual file that is passed to `renderImports` (#25445)
Previously we were just checking that the object was "any" object but now
we check that it is the file object that we expected.

PR Close #25445
2019-05-16 12:11:03 -07:00
Ben Lesh cf86ed7b29 refactor(ivy): migrate ɵɵ prefix back to Δ (#30362)
Now that issues are resolved with Closure compiler, we can move back to our desired prefix of `Δ`.

PR Close #30362
2019-05-14 16:52:15 -07:00
Pete Bacon Darwin ef861958a9 refactor(ivy): ngcc - add MockFileSystem (#29643)
PR Close #29643
2019-04-29 12:37:21 -07:00
Pete Bacon Darwin 16d7dde2ad refactor(ivy): ngcc - implement abstract FileSystem (#29643)
This commit introduces a new interface, which abstracts access
to the underlying `FileSystem`. There is initially one concrete
implementation, `NodeJsFileSystem`, which is simply wrapping the
`fs` library of NodeJs.

Going forward, we can provide a `MockFileSystem` for test, which
should allow us to stop using `mock-fs` for most of the unit tests.
We could also implement a `CachedFileSystem` that may improve the
performance of ngcc.

PR Close #29643
2019-04-29 12:37:21 -07:00
Pete Bacon Darwin 78b5bd5174 refactor(compiler-cli): ngcc - remove unnecessary `sourcePath` parameters (#29643)
The `Transformer` and `Renderer` classes do not
actually need a `sourcePath` value as by the time
they are doing their work we are only working directly
with full absolute paths.

PR Close #29643
2019-04-29 12:37:20 -07:00
JoostK 8c80b851c8 fix(ivy): ngcc - insert new imports after existing ones (#30029)
Previously, ngcc would insert new imports at the beginning of the file, for
convenience. This is problematic for imports that have side-effects, as the
side-effects imposed by such imports may affect the behavior of subsequent
imports.

This commit teaches ngcc to insert imports after any existing imports. Special
care has been taken to ensure inserted constants will still follow after the
inserted imports.

Resolves FW-1271

PR Close #30029
2019-04-22 16:29:30 -07:00
Alex Rickabaugh b0578061ce refactor(ivy): use ɵɵ instead of Δ for now (#29850)
The `Δ` caused issue with other infrastructure, and we are temporarily
changing it to `ɵɵ`.

This commit also patches ts_api_guardian_test and AIO to understand `ɵɵ`.

PR Close #29850
2019-04-11 16:27:56 -07:00
Ben Lesh 138ca5a246 refactor(ivy): prefix all generated instructions (#29692)
- Updates all instructions to be prefixed with the Greek delta symbol

PR Close #29692
2019-04-10 12:11:40 -07:00
JoostK 45c6360e5a feat(ivy): emit module scope metadata using pure function call (#29598)
Prior to this change, all module metadata would be included in the
`defineNgModule` call that is set as the `ngModuleDef` field of module
types. Part of the metadata is scope information like declarations,
imports and exports that is used for computing the transitive module
scope in JIT environments, preventing those references from being
tree-shaken for production builds.

This change moves the metadata for scope computations to a pure function
call that patches the scope references onto the module type. Because the
function is marked pure, it may be tree-shaken out during production builds
such that references to declarations and exports are dropped, which in turn
allows for tree-shaken any declaration that is not otherwise referenced.

Fixes #28077, FW-1035

PR Close #29598
2019-04-02 16:03:54 -07:00
Pete Bacon Darwin 8d3d75e454 feat(compiler-cli): ngcc - make logging more configurable (#29591)
This allows CLI usage to filter excessive log messages
and integrations like webpack plugins to provide their own logger.

// FW-1198

PR Close #29591
2019-04-01 11:53:28 -07:00
Pete Bacon Darwin 1df9908579 fix(ivy): ngcc - ensure generated source map paths are correct (#29556)
Previously we were using absolute paths, but since at rendering time
we do not know exactly where the file will be written it is more correct
to  change to using relative paths. This is actually better all round
since it allows the folders to be portable to different machines, etc.

PR Close #29556
2019-03-28 15:23:35 -07:00
Pete Bacon Darwin c456b73302 refactor(ivy): ngcc - remove the `targetPath` properties of Transformer and Renderer (#29556)
We have already removed this concept from the public API. This just cleans it out altogether.

The `targetPath` was an alternative output path to the original `basePath`.
This is not really a very useful concept, since the actual target path
of each output file is more complex and not consistently relative to the `basePath`.

PR Close #29556
2019-03-28 15:23:35 -07:00
Ben Lesh 96b800c8bc feat(ivy): select instruction now generated in front of all relevant instructions (#29546)
PR Close #29546
2019-03-27 12:37:03 -07:00
Pete Bacon Darwin 64e5628897 feat(ivy): ngcc - support creating a new copy of the entry-point format (#29092)
This commit adds a `NewEntryPointFileWriter` that will be used in
webpack integration. Instead of overwriting files in-place, this `FileWriter`
will make a copy of the TS program files and write the transformed files
there. It also updates the package.json with new properties that can be
used to access the new entry-point format.

FW-1121

PR Close #29092
2019-03-20 14:45:55 -04:00
Pete Bacon Darwin c9f7cdaafd refactor(ivy): ngcc - simplify `Transformer.transform` API (#29092)
By ensuring that EntryPointBundle contains everything that `Transformer.transform()`
needs to do its work, we can simplify its signature.

PR Close #29092
2019-03-20 14:45:54 -04:00
Pete Bacon Darwin a770aa231d refactor(ivy): move ngcc into a higher level folder (#29092)
PR Close #29092
2019-03-20 14:45:54 -04:00