diff --git a/src/client/queue-client.ts b/src/client/queue-client.ts index 5ea8bbf91e5..2a287a866ce 100644 --- a/src/client/queue-client.ts +++ b/src/client/queue-client.ts @@ -4,6 +4,7 @@ import * as d from '../declarations'; export function createQueueClient(App: d.AppGlobal, win: Window): d.QueueApi { const now: d.Now = () => win.performance.now(); + const async = App.asyncQueue !== false; const resolved = Promise.resolve(); const highPriority: d.RafCallback[] = []; const domReads: d.RafCallback[] = []; @@ -65,11 +66,13 @@ export function createQueueClient(App: d.AppGlobal, win: Window): d.QueueApi { // DOM READS!!! consume(domReads); - const start = now() + (7 * Math.ceil(congestion * (1.0 / 22.0))); + const timeout = async + ? now() + (7 * Math.ceil(congestion * (1.0 / 22.0))) + : Infinity; // DOM WRITES!!! - consumeTimeout(domWrites, start); - consumeTimeout(domWritesLow, start); + consumeTimeout(domWrites, timeout); + consumeTimeout(domWritesLow, timeout); if (domWrites.length > 0) { domWritesLow.push(...domWrites); diff --git a/src/compiler/app/reserved-properties.ts b/src/compiler/app/reserved-properties.ts index a6ff2f5b68c..3bc78728e3a 100644 --- a/src/compiler/app/reserved-properties.ts +++ b/src/compiler/app/reserved-properties.ts @@ -29,6 +29,7 @@ export const RESERVED_PROPERTIES: string[] = [ 'ael', 'rel', 'raf', + 'asyncQueue', 'read', 'ref', 'resourcesUrl', diff --git a/src/compiler/bundle/derive-modules.ts b/src/compiler/bundle/derive-modules.ts index 2f21705c5e6..18bcfe32b17 100644 --- a/src/compiler/bundle/derive-modules.ts +++ b/src/compiler/bundle/derive-modules.ts @@ -13,7 +13,7 @@ export async function deriveModules(config: d.Config, compilerCtx: d.CompilerCtx } const modules = await Promise.all([ deriveModule(config, compilerCtx, buildCtx, 'es2017', true, true, moduleFormats.esm), // browser ES2017 - deriveModule(config, compilerCtx, buildCtx, 'es2017', false, false, moduleFormats.esm), // esm ES2017 + deriveModule(config, compilerCtx, buildCtx, 'es2017', false, false, moduleFormats.esm), // esm ES2017 deriveModule(config, compilerCtx, buildCtx, 'es5', false, true, moduleFormats.esm), // esm ES5 deriveModule(config, compilerCtx, buildCtx, 'es5', true, true, moduleFormats.amd), // browser ES5 ]); diff --git a/src/compiler/config/validate-outputs-angular.ts b/src/compiler/config/validate-outputs-angular.ts index 8b8576393d0..ad005701d5e 100644 --- a/src/compiler/config/validate-outputs-angular.ts +++ b/src/compiler/config/validate-outputs-angular.ts @@ -9,6 +9,7 @@ export function validateOutputTargetAngular(config: d.Config) { distOutputTargets.forEach(outputTarget => { outputTarget.excludeComponents = outputTarget.excludeComponents || []; + outputTarget.useDirectives = !!outputTarget.useDirectives; if (!path.isAbsolute(outputTarget.directivesProxyFile)) { outputTarget.directivesProxyFile = normalizePath(path.join(config.rootDir, outputTarget.directivesProxyFile)); diff --git a/src/compiler/distribution/dist-angular.ts b/src/compiler/distribution/dist-angular.ts index f7a89b7bdeb..0fb390f426b 100644 --- a/src/compiler/distribution/dist-angular.ts +++ b/src/compiler/distribution/dist-angular.ts @@ -26,7 +26,8 @@ function getComponents(excludeComponents: string[], cmpRegistry: d.ComponentRegi async function angularDirectiveProxyOutput(config: d.Config, compilerCtx: d.CompilerCtx, outputTarget: d.OutputTargetAngular, cmpRegistry: d.ComponentRegistry) { const components = getComponents(outputTarget.excludeComponents, cmpRegistry); - const { hasDirectives, hasOutputs, proxies } = generateProxies(components); + const useDirectives = outputTarget.useDirectives; + const { hasOutputs, proxies } = generateProxies(components, useDirectives); const auxFunctions: string[] = [ inputsAuxFunction(), @@ -37,10 +38,15 @@ async function angularDirectiveProxyOutput(config: d.Config, compilerCtx: d.Comp 'ElementRef' ]; - if (hasDirectives) { - angularImports.push('Component'); - angularImports.push('ViewEncapsulation'); - angularImports.push('ChangeDetectionStrategy'); + if (components.length > 0) { + if (useDirectives) { + angularImports.push('Directive'); + } else { + angularImports.push('Component'); + angularImports.push('ViewEncapsulation'); + angularImports.push('ChangeDetectionStrategy'); + angularImports.push('ChangeDetectorRef'); + } } if (hasOutputs) { @@ -111,15 +117,13 @@ export function proxyMethods(instance: any, el: any, methods: string[]) { `; } -function generateProxies(components: d.ComponentMeta[]) { - let hasDirectives = false; +function generateProxies(components: d.ComponentMeta[], useDirectives: boolean) { let hasMethods = false; let hasOutputs = false; let hasInputs = false; const lines = components.map(cmpMeta => { - const proxy = generateProxy(cmpMeta); - hasDirectives = true; + const proxy = generateProxy(cmpMeta, useDirectives); if (proxy.hasInputs) { hasInputs = true; } @@ -134,14 +138,13 @@ function generateProxies(components: d.ComponentMeta[]) { return { proxies: lines.join('\n'), - hasDirectives, hasInputs, hasMethods, hasOutputs }; } -function generateProxy(cmpMeta: d.ComponentMeta) { +function generateProxy(cmpMeta: d.ComponentMeta, useDirectives: boolean) { // Collect component meta const inputs = getInputs(cmpMeta); const outputs = getOutputs(cmpMeta); @@ -154,12 +157,17 @@ function generateProxy(cmpMeta: d.ComponentMeta) { const hasContructor = hasInputs || hasOutputs || hasMethods; // Generate Angular @Directive + const decorator = useDirectives ? 'Directive' : 'Component'; const directiveOpts = [ `selector: \'${cmpMeta.tagNameMeta}\'`, - `changeDetection: ChangeDetectionStrategy.OnPush`, - `encapsulation: ViewEncapsulation.None`, - `template: ''` ]; + if (!useDirectives) { + directiveOpts.push( + `changeDetection: ChangeDetectionStrategy.OnPush`, + `encapsulation: ViewEncapsulation.None`, + `template: ''` + ); + } if (inputs.length > 0) { directiveOpts.push(`inputs: ['${inputs.join(`', '`)}']`); } @@ -167,7 +175,7 @@ function generateProxy(cmpMeta: d.ComponentMeta) { const tagNameAsPascal = dashToPascalCase(cmpMeta.tagNameMeta); const lines = [` export declare interface ${cmpMeta.componentClass} extends StencilComponents<'${tagNameAsPascal}'> {} -@Component({ ${directiveOpts.join(', ')} }) +@${decorator}({ ${directiveOpts.join(', ')} }) export class ${cmpMeta.componentClass} {`]; // Generate outputs @@ -177,9 +185,16 @@ export class ${cmpMeta.componentClass} {`]; // Generate component constructor if (hasContructor) { - lines.push(` + if (useDirectives) { + lines.push(` constructor(r: ElementRef) { const el = r.nativeElement;`); + } else { + lines.push(` + constructor(c: ChangeDetectorRef, r: ElementRef) { + c.detach(); + const el = r.nativeElement;`); + } } if (hasMethods) { diff --git a/src/declarations/app-global.ts b/src/declarations/app-global.ts index 8047c0611cb..7d7c9c74370 100644 --- a/src/declarations/app-global.ts +++ b/src/declarations/app-global.ts @@ -26,6 +26,7 @@ export interface WindowData extends Window { export interface AppGlobal { ael?: (elm: Element|Document|Window, eventName: string, cb: d.EventListenerCallback, opts?: d.ListenOptions) => void; + asyncQueue?: boolean; resourcesUrl?: string; componentOnReady?: (elm: d.HostElement, resolve: (elm: d.HostElement) => void) => boolean; Context?: any; diff --git a/src/declarations/output-targets.ts b/src/declarations/output-targets.ts index 646306b5317..3136d3c6f23 100644 --- a/src/declarations/output-targets.ts +++ b/src/declarations/output-targets.ts @@ -193,6 +193,7 @@ export interface OutputTargetAngular extends OutputTargetBase { directivesProxyFile?: string; directivesArrayFile?: string; excludeComponents?: string[]; + useDirectives?: boolean; }