From 3a6e7b5d2a54d011832191b96df5d8fd28a28740 Mon Sep 17 00:00:00 2001 From: JoostK Date: Mon, 16 Mar 2020 21:42:58 +0100 Subject: [PATCH] docs: explain foreign function/value constraints in Ivy compatibility examples (#36092) Addresses documentation gaps as reported in #35078. The documentation only contained a single statement on foreign function/value compatibility without going into detail on what this means. This commit adds several examples to the Ivy compatibility guide and explains why Ivy behaves differently compared to VE. PR Close #36092 --- .../guide/ivy-compatibility-examples.md | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/aio/content/guide/ivy-compatibility-examples.md b/aio/content/guide/ivy-compatibility-examples.md index bbfa526edd..ceda4cec5d 100644 --- a/aio/content/guide/ivy-compatibility-examples.md +++ b/aio/content/guide/ivy-compatibility-examples.md @@ -348,3 +348,72 @@ To fix this problem, we recommend either getting the information for the binding {{ myName }}
``` + +{@a foreign-values} +## Foreign functions and foreign values aren't statically resolvable + +### Basic example of change + +Consider a library that defines and exports some selector string to be used in other libraries: + +``` +export let mySelector = '[my-selector]'; +``` + +This selector is then imported in another library or an application: + +``` +import {mySelector} from 'my-library'; + +@Directive({selector: mySelector}) +export class MyDirective {} +``` + +Because the `mySelector` value is imported from an external library, it is part of a different compilation unit and therefore considered _foreign_. + +While this code would work correctly in the View Engine compiler, it would fail to compile in Ivy in AOT mode. + +### Background + +In View Engine, the compiler would capture the source code of a library in `metadata.json` files when bundling the library, so that external consumers could "look inside" the source code of an external library. +When AOT-compiling the application, the `metadata.json` files would be used to determine the value of `mySelector`. +In Ivy, the `metadata.json` files are no longer used. Instead, the compiler extracts metadata for external libraries from the `.d.ts` files that TypeScript creates. +This has several benefits such as better performance, much improved error reporting, and enables more build caching opportunities as there is no longer a dependency on library internals. + +Looking back at the previous example, the `mySelector` value would be represented in the `.d.ts` as follows: + +``` +export declare let mySelector: string; +``` + +Notice that the actual value of the selector is no longer present, so that the Ivy compiler is unable to use it during AOT compilations. + +### Example of error + +In the above example, a compilation error would occur when compiling `MyDirective`: + +``` +error NG1010: selector must be a string + Value is a reference to 'mySelector'. + + 1 export declare let mySelector: string; + ~~~~~~~~~~ + Reference is declared here. + +``` + +### Recommended fix + +When exporting values from a library, ensure the actual value is present in the `.d.ts` file. This typically requires that the variable be declared as a constant: + +``` +export const mySelector = '[my-selector]'; +``` + +In classes, a field should be declared using the `static readonly` modifiers: + +``` +export class Selectors { + static readonly mySelector = '[my-selector]'; +} +```