1 | /**
|
2 | * This file describes the interface between compilation time
|
3 | * and runtime.
|
4 | *
|
5 | * # Locators
|
6 | *
|
7 | * Compile time and runtime must share the same Locator. A Locator is an
|
8 | * object that describes the location of a template, and is roughly a
|
9 | * module name. The compiler and runtime may use the Locator to locally
|
10 | * resolve names relative to the template the name was found in, but must
|
11 | * share resolution rules between compilation time and runtime.
|
12 | *
|
13 | * For example, given this template with Locator
|
14 | * `{ module: 'components/Articles/Container' }:
|
15 | *
|
16 | * ```
|
17 | * <TabBar />
|
18 | * ```
|
19 | *
|
20 | * The compiler may resolve `<TabBar>` to `components/Articles/TabBar`. The
|
21 | * important thing is that the compiler and runtime share resolution rules.
|
22 | *
|
23 | * # CompileTimeLookup
|
24 | *
|
25 | * When compiling an application, the `CompileTimeLookup` is responsible
|
26 | * for resolving helpers, modifiers, components, and partials into "handles"
|
27 | * (numbers) that can be embedded into the program and used at runtime.
|
28 | *
|
29 | * # RuntimeResolver
|
30 | *
|
31 | * The `RuntimeResolver` has two responsibilities.
|
32 | *
|
33 | * 1. To turn handles created by the `CompileTimeLookup` into live helpers,
|
34 | * modifiers, components, and partials.
|
35 | * 2. To resolve dynamic components and partials at runtime that come from
|
36 | * calls to `{{component dynamic}}` or `{{partial dynamic}}`.
|
37 | *
|
38 | * The `CompileTimeLookup` and `RuntimeResolver` must maintain symmetry
|
39 | * between:
|
40 | *
|
41 | * * `resolver.resolve(lookup.lookupComponentDefinition(name, referrer))`; and
|
42 | * * `resolver.lookupComponentDefinition(name, referrer))`
|
43 | *
|
44 | * And between:
|
45 | *
|
46 | * * `resolver.resolve(lookup.lookupPartial(name, referrer))`; and
|
47 | * * `resolver.lookupPartial(name, referrer))`
|
48 | *
|
49 | * # Coupling
|
50 | *
|
51 | * In practice, the `CompileTimeLookup` and `RuntimeResolver` are two parts
|
52 | * of one system. The goal of this system is to allow the `CompileTimeLookup`
|
53 | * to do as much resolution as possible ahead of time, while still allowing
|
54 | * the `RuntimeResolver` to do dynamic resolution when necessary.
|
55 | */
|
56 |
|
57 | import { Option } from './core';
|
58 | import { ProgramSymbolTable } from './tier1/symbol-table';
|
59 | import { ComponentDefinitionState, ComponentInstanceState } from './components';
|
60 | import { CompilableProgram, Template, HandleResult } from './template';
|
61 | import { CompileTimeCompilationContext } from './program';
|
62 | import { Owner, ModifierDefinitionState, HelperDefinitionState } from './runtime';
|
63 | import { InternalComponentCapability, InternalComponentManager } from './managers';
|
64 |
|
65 | export interface CompileTimeComponent {
|
66 | handle: number;
|
67 | capabilities: InternalComponentCapability;
|
68 | compilable: Option<CompilableProgram>;
|
69 | }
|
70 |
|
71 | export interface ResolvedComponentDefinition<
|
72 | D = ComponentDefinitionState,
|
73 | I = ComponentInstanceState,
|
74 | M extends InternalComponentManager<I, D> = InternalComponentManager<I, D>
|
75 | > {
|
76 | state: D;
|
77 | manager: M;
|
78 | template: Template | null;
|
79 | }
|
80 |
|
81 | export const enum ResolverContext {
|
82 | Component,
|
83 | Modifier,
|
84 | Helper,
|
85 | HelperOrComponent,
|
86 | }
|
87 |
|
88 | export interface CompileTimeResolver<O extends Owner = Owner> {
|
89 | lookupHelper(name: string, owner: O): Option<HelperDefinitionState>;
|
90 | lookupModifier(name: string, owner: O): Option<ModifierDefinitionState>;
|
91 | lookupComponent(name: string, owner: O): Option<ResolvedComponentDefinition>;
|
92 | lookupPartial(name: string, owner: O): Option<PartialDefinition>;
|
93 |
|
94 | // TODO: These are used to lookup keywords that are implemented as helpers/modifiers.
|
95 | // We should try to figure out a cleaner way to do this.
|
96 | lookupBuiltInHelper(name: string): Option<HelperDefinitionState>;
|
97 | lookupBuiltInModifier(name: string): Option<ModifierDefinitionState>;
|
98 | }
|
99 |
|
100 | export interface PartialDefinition {
|
101 | name: string; // for debugging
|
102 |
|
103 | getPartial(
|
104 | context: CompileTimeCompilationContext
|
105 | ): { symbolTable: ProgramSymbolTable; handle: HandleResult };
|
106 | }
|
107 |
|
108 | export interface RuntimeResolver<O extends Owner = Owner> {
|
109 | lookupComponent(name: string, owner: O): Option<ResolvedComponentDefinition>;
|
110 | lookupPartial(name: string, owner: O): Option<PartialDefinition>;
|
111 | }
|