private async executeSchematic(
    collectionName: string,
    options: string[] = [],
  ): Promise<number | void> {
    const runOptions: RunSchematicOptions = {
      schematicOptions: options,
      collectionName,
      schematicName: 'ng-add',
      dryRun: false,
      force: false,
    };

    try {
      return await this.runSchematic(runOptions);
    } catch (e) {
      if (e instanceof NodePackageDoesNotSupportSchematics) {
        this.logger.error(tags.oneLine`
          The package that you are trying to add does not support schematics. You can try using
          a different version of the package or contact the package author to add ng-add support.
        `);

        return 1;
      }

      throw e;
    }
  }


private async findProjectVersion(name: string): Promise<string | null> {
    let installedPackage;
    try {
      installedPackage = require.resolve(join(name, 'package.json'), {
        paths: [this.workspace.root],
      });
    } catch {}

    if (installedPackage) {
      try {
        const installed = await fetchPackageManifest(dirname(installedPackage), this.logger);

        return installed.version;
      } catch {}
    }

    let projectManifest;
    try {
      projectManifest = await fetchPackageManifest(this.workspace.root, this.logger);
    } catch {}

    if (projectManifest) {
      const version = projectManifest.dependencies[name] || projectManifest.devDependencies[name];
      if (version) {
        return version;
      }
    }

    return null;
  }


private async hasMismatchedPeer(manifest: PackageManifest): Promise<boolean> {
    for (const peer in manifest.peerDependencies) {
      let peerIdentifier;
      try {
        peerIdentifier = npa.resolve(peer, manifest.peerDependencies[peer]);
      } catch {
        this.logger.warn(`Invalid peer dependency ${peer} found in package.`);
        continue;
      }

      if (peerIdentifier.type === 'version' || peerIdentifier.type === 'range') {
        try {
          const version = await this.findProjectVersion(peer);
          if (!version) {
            continue;
          }

          // tslint:disable-next-line:no-any
          const options = { includePrerelease: true } as any;

          if (
            !intersects(version, peerIdentifier.rawSpec, options) &&
            !satisfies(version, peerIdentifier.rawSpec, options)
          ) {
            return true;
          }
        } catch {
          // Not found or invalid so ignore
          continue;
        }
      } else {
        // type === 'tag' | 'file' | 'directory' | 'remote' | 'git'
        // Cannot accurately compare these as the tag/location may have changed since install
      }
    }

    return false;
  }


()=> console.warn('AG Grid: The PopupTextCellEditor (agPopupTextCellEditor) is deprecated. Instead use {cellEditor: "agTextCellEditor", cellEditorPopup: true} ')


export class PopupTextCellEditor extends TextCellEditor {

    constructor() {
        super();
        doOnce( ()=> console.warn('AG Grid: The PopupTextCellEditor (agPopupTextCellEditor) is deprecated. Instead use {cellEditor: "agTextCellEditor", cellEditorPopup: true} '), 'PopupTextCellEditor.deprecated');
    }

    public isPopup(): boolean {
        return true;
    }

}


public isPopup(): boolean {
        return true;
    }


() => ({
  history: { location: { pathname: '/' } },
})


() => {
  history = createMemoryHistory({ initialEntries: ['/', '/en-US'], initialIndex: 0 });
  const baseCtx = {
    title: 'test',
    locale: 'zh-CN',
    routes: [
      {
        path: '/',
        title: '首页',
        meta: {},
      },
      {
        path: '/en-US',
        title: 'Home',
        meta: {},
      },
    ],
    config: {
      locales: [
        { name: 'zh-CN', label: '中文' },
        { name: 'en-US', label: 'English' },
      ],
      menus: {},
      navs: {},
      title: 'test',
      logo: '/',
      mode: 'site' as 'doc' | 'site',
      repository: { branch: 'master' },
    },
    meta: {},
    menu: [
      {
        title: '分组',
        children: [
          {
            title: 'English',
            path: '/en',
          },
        ],
      },
    ],
    nav: [
      {
        path: '/',
        title: '首页',
        children: [],
      },
      {
        title: '生态',
        children: [
          {
            path: 'https://d.umijs.org',
            title: 'GitHub',
            children: [],
          },
        ],
      },
    ],
    base: '/',
    apis: {
      MultipleExports: {
        Other: [
          {
            identifier: 'other',
            type: 'string',
          },
        ],
      },
    }
  };
  const baseProps = {
    history,
    location: { ...history.location, query: {} },
    match: { params: {}, isExact: true, path: '/', url: '/' },
    route: { path: '/', routes: baseCtx.routes },
  };

  it('should render site home page', () => {
    const attrName = 'data-prefers-color';
    document.documentElement.setAttribute(attrName, 'light');
    localStorage.setItem('dumi:prefers-color', 'light');
    const wrapper = ({ children }) => (
      <Context.Provider
        value={{
          ...baseCtx,
          meta: {
            title: 'test',
            hero: {
              title: 'Hero',
              desc: 'Hero Description',
              actions: [{ text: '开始', link: '/' }],
            },
            features: [
              { title: 'Feat', desc: 'Feature' },
              { title: 'Feat2', link: '/' },
            ],
          },
        }}
      >
        {children}
      </Context.Provider>
    );
    const { container, getAllByText, getByText } = render(
      <Router history={history}>
        <Layout {...baseProps}>

Home Page

        </Layout>
      </Router>,
      { wrapper },
    );

    // expect navbar be rendered
    expect(getAllByText('首页')).not.toBeNull();

    // expect content be rendered
    expect(getByText('Home Page')).not.toBeNull();

    // expect hero be rendered
    expect(getByText('Hero')).not.toBeNull();

    // expect features be rendered
    expect(getByText('Feature')).not.toBeNull();
    expect(getByText('Feat2')).not.toBeNull();

    // trigger mobile menu display
    queryByAttribute('class', container, '__dumi-default-navbar-toggle').click();

    // expect sidemenu display for mobile
    expect(queryByAttribute('data-mobile-show', container, 'true')).not.toBeNull();

    // expect dark render and click success
    const menu = queryByAttribute('class', container, '__dumi-default-menu');
    const sunMenu = queryByAttribute('class', menu, '__dumi-default-dark-sun __dumi-default-dark-switch-active');
    expect(sunMenu).not.toBeNull();
    const moonMenu = queryByAttribute('class', container, '__dumi-default-dark-moon');
    expect(moonMenu).not.toBeNull();
    moonMenu.click();
    expect(document.documentElement.getAttribute(attrName)).toEqual('dark');
    expect(queryByAttribute('data-mobile-show', container, 'true')).toBeNull();

    const navbar = queryByAttribute('class', container, '__dumi-default-navbar');
    const moonNav = queryByAttribute('class', navbar, '__dumi-default-dark-moon __dumi-default-dark-switch-active');
    moonNav.click();
    expect(queryByAttribute('class', navbar, '__dumi-default-dark-switch __dumi-default-dark-switch-open')).not.toBeNull();
    const switchList = queryByAttribute('class', navbar, '__dumi-default-dark-switch-list');
    expect(switchList).not.toBeNull();
    queryByAttribute('class', switchList, '__dumi-default-dark-sun').click();
    expect(document.documentElement.getAttribute(attrName)).toEqual('light');
    expect(queryByAttribute('class', navbar, '__dumi-default-dark-switch-list')).toBeNull();
    expect(queryByAttribute('class', navbar, '__dumi-default-dark-switch __dumi-default-dark-switch-open')).toBeNull();
  }


() => {
    const attrName = 'data-prefers-color';
    document.documentElement.setAttribute(attrName, 'light');
    localStorage.setItem('dumi:prefers-color', 'light');
    const wrapper = ({ children }) => (
      <Context.Provider
        value={{
          ...baseCtx,
          meta: {
            title: 'test',
            hero: {
              title: 'Hero',
              desc: 'Hero Description',
              actions: [{ text: '开始', link: '/' }],
            },
            features: [
              { title: 'Feat', desc: 'Feature' },
              { title: 'Feat2', link: '/' },
            ],
          },
        }}


({ children }) => (
      <Context.Provider
        value={


async () => {
    const updatedTime = 1604026996000;
    const wrapper = ({ children }) => (
      <Context.Provider
        value={{
          ...baseCtx,
          meta: {
            title: 'test',
            slugs: [{ value: 'Slug A', heading: 'a', depth: 2 }],
            updatedTime,
            filePath: 'temp',
          },
        }}


() => {
    const code = "console.log('Hello World!')";
    const wrapper = ({ children }) => (
      <Context.Provider
        value={{
          ...baseCtx,
          meta: {
            title: 'test',
            slugs: [{ value: 'Slug A', heading: 'a', depth: 2 }],
          },
        }}


export interface WithKey {
  key: string
}


export interface WithProjectType {
  projectType: Projects
}


export interface WithProjectTypeSetter {
  setProjectType: React.Dispatch<React.SetStateAction<Projects>>
}


export enum Projects {
  COMMUNITY,
  CLUBS,
  RESEARCH,
}


export enum Tech {
  C = 'C',
  CSS = 'CSS',
  EXCEL = 'Excel',
  HTML = 'HTML',
  JAVA = 'Java',
  JAVASCRIPT = 'JavaScript',
  MSACCESS = 'MS Access',
  NODE = 'Node.js',
  POSTGRES = 'PostgreSQL',
  PYTHON = 'Python',
  REACT = 'React',
  SQL = 'SQL',
  TYPESCRIPT = 'TypeScript',
  MONGODB = 'MongoDB',
  REDUX = 'Redux',
  FLASK = 'Flask',
}


class Api implements ApiInterface {
  protected httpClient: any;

  constructor(settings: ApiSettingsInterface) {
    this.httpClient = settings.httpClient;
  }
}


export interface ApiSettingsInterface {
  httpClient: any;
}


export interface ApiInterface {}


async () => await redis.incr(idKey)


function baseDirectiveFields(
    meta: R3DirectiveMetadata, constantPool: ConstantPool,
    bindingParser: BindingParser): DefinitionMap {
  const definitionMap = new DefinitionMap();
  const selectors = core.parseSelectorToR3Selector(meta.selector);

  // e.g. `type: MyDirective`
  definitionMap.set('type', meta.internalType);

  // e.g. `selectors: [['', 'someDir', '']]`
  if (selectors.length > 0) {
    definitionMap.set('selectors', asLiteral(selectors));
  }

  if (meta.queries.length > 0) {
    // e.g. `contentQueries: (rf, ctx, dirIndex) => { ... }
    definitionMap.set(
        'contentQueries', createContentQueriesFunction(meta.queries, constantPool, meta.name));
  }

  if (meta.viewQueries.length) {
    definitionMap.set(
        'viewQuery', createViewQueriesFunction(meta.viewQueries, constantPool, meta.name));
  }

  // e.g. `hostBindings: (rf, ctx) => { ... }
  definitionMap.set(
      'hostBindings',
      createHostBindingsFunction(
          meta.host, meta.typeSourceSpan, bindingParser, constantPool, meta.selector || '',
          meta.name, definitionMap));

  // e.g 'inputs: {a: 'a'}`
  definitionMap.set('inputs', conditionallyCreateMapObjectLiteral(meta.inputs, true));

  // e.g 'outputs: {a: 'a'}`
  definitionMap.set('outputs', conditionallyCreateMapObjectLiteral(meta.outputs));

  if (meta.exportAs !== null) {
    definitionMap.set('exportAs', o.literalArr(meta.exportAs.map(e => o.literal(e))));
  }

  return definitionMap;
}


/**
 * Add features to the definition map.
 */
function addFeatures(definitionMap: DefinitionMap, meta: R3DirectiveMetadata|R3ComponentMetadata) {
  // e.g. `features: [NgOnChangesFeature]`
  const features: o.Expression[] = [];

  const providers = meta.providers;
  const viewProviders = (meta as R3ComponentMetadata).viewProviders;
  if (providers || viewProviders) {
    const args = [providers || new o.LiteralArrayExpr([])];
    if (viewProviders) {
      args.push(viewProviders);
    }
    features.push(o.importExpr(R3.ProvidersFeature).callFn(args));
  }

  if (meta.usesInheritance) {
    features.push(o.importExpr(R3.InheritDefinitionFeature));
  }
  if (meta.fullInheritance) {
    features.push(o.importExpr(R3.CopyDefinitionFeature));
  }
  if (meta.lifecycle.usesOnChanges) {
    features.push(o.importExpr(R3.NgOnChangesFeature));
  }
  if (features.length) {
    definitionMap.set('features', o.literalArr(features));
  }
}


/**
 * Compile a directive for the render3 runtime as defined by the `R3DirectiveMetadata`.
 */
export function compileDirectiveFromMetadata(
    meta: R3DirectiveMetadata, constantPool: ConstantPool,
    bindingParser: BindingParser): R3DirectiveDef {
  const definitionMap = baseDirectiveFields(meta, constantPool, bindingParser);
  addFeatures(definitionMap, meta);
  const expression = o.importExpr(R3.defineDirective).callFn([definitionMap.toLiteralMap()]);

  const typeParams = createDirectiveTypeParams(meta);
  const type = o.expressionType(o.importExpr(R3.DirectiveDefWithMeta, typeParams));

  return {expression, type};
}


/**
 * Compile a component for the render3 runtime as defined by the `R3ComponentMetadata`.
 */
export function compileComponentFromMetadata(
    meta: R3ComponentMetadata, constantPool: ConstantPool,
    bindingParser: BindingParser): R3ComponentDef {
  const definitionMap = baseDirectiveFields(meta, constantPool, bindingParser);
  addFeatures(definitionMap, meta);

  const selector = meta.selector && CssSelector.parse(meta.selector);
  const firstSelector = selector && selector[0];

  // e.g. `attr: ["class", ".my.app"]`
  // This is optional an only included if the first selector of a component specifies attributes.
  if (firstSelector) {
    const selectorAttributes = firstSelector.getAttrs();
    if (selectorAttributes.length) {
      definitionMap.set(
          'attrs',
          constantPool.getConstLiteral(
              o.literalArr(selectorAttributes.map(
                  value => value != null ? o.literal(value) : o.literal(undefined))),
              /* forceShared */ true));
    }
  }

  // Generate the CSS matcher that recognize directive
  let directiveMatcher: SelectorMatcher|null = null;

  if (meta.directives.length > 0) {
    const matcher = new SelectorMatcher();
    for (const {selector, expression} of meta.directives) {
      matcher.addSelectables(CssSelector.parse(selector), expression);
    }
    directiveMatcher = matcher;
  }

  // e.g. `template: function MyComponent_Template(_ctx, _cm) {...}`
  const templateTypeName = meta.name;
  const templateName = templateTypeName ? `${templateTypeName}_Template` : null;

  const directivesUsed = new Set<o.Expression>();
  const pipesUsed = new Set<o.Expression>();
  const changeDetection = meta.changeDetection;

  const template = meta.template;
  const templateBuilder = new TemplateDefinitionBuilder(
      constantPool, BindingScope.createRootScope(), 0, templateTypeName, null, null, templateName,
      directiveMatcher, directivesUsed, meta.pipes, pipesUsed, R3.namespaceHTML,
      meta.relativeContextFilePath, meta.i18nUseExternalIds);

  const templateFunctionExpression = templateBuilder.buildTemplateFunction(template.nodes, []);

  // We need to provide this so that dynamically generated components know what
  // projected content blocks to pass through to the component when it is instantiated.
  const ngContentSelectors = templateBuilder.getNgContentSelectors();
  if (ngContentSelectors) {
    definitionMap.set('ngContentSelectors', ngContentSelectors);
  }

  // e.g. `decls: 2`
  definitionMap.set('decls', o.literal(templateBuilder.getConstCount()));

  // e.g. `vars: 2`
  definitionMap.set('vars', o.literal(templateBuilder.getVarCount()));

  // Generate `consts` section of ComponentDef:
  // - either as an array:
  //   `consts: [['one', 'two'], ['three', 'four']]`
  // - or as a factory function in case additional statements are present (to support i18n):
  //   `consts: function() { var i18n_0; if (ngI18nClosureMode) {...} else {...} return [i18n_0]; }`
  const {constExpressions, prepareStatements} = templateBuilder.getConsts();
  if (constExpressions.length > 0) {
    let constsExpr: o.LiteralArrayExpr|o.FunctionExpr = o.literalArr(constExpressions);
    // Prepare statements are present - turn `consts` into a function.
    if (prepareStatements.length > 0) {
      constsExpr = o.fn([], [...prepareStatements, new o.ReturnStatement(constsExpr)]);
    }
    definitionMap.set('consts', constsExpr);
  }

  definitionMap.set('template', templateFunctionExpression);

  // e.g. `directives: [MyDirective]`
  if (directivesUsed.size) {
    let directivesExpr: o.Expression = o.literalArr(Array.from(directivesUsed));
    if (meta.wrapDirectivesAndPipesInClosure) {
      directivesExpr = o.fn([], [new o.ReturnStatement(directivesExpr)]);
    }
    definitionMap.set('directives', directivesExpr);
  }

  // e.g. `pipes: [MyPipe]`
  if (pipesUsed.size) {
    let pipesExpr: o.Expression = o.literalArr(Array.from(pipesUsed));
    if (meta.wrapDirectivesAndPipesInClosure) {
      pipesExpr = o.fn([], [new o.ReturnStatement(pipesExpr)]);
    }
    definitionMap.set('pipes', pipesExpr);
  }

  if (meta.encapsulation === null) {
    meta.encapsulation = core.ViewEncapsulation.Emulated;
  }

  // e.g. `styles: [str1, str2]`
  if (meta.styles && meta.styles.length) {
    const styleValues = meta.encapsulation == core.ViewEncapsulation.Emulated ?
        compileStyles(meta.styles, CONTENT_ATTR, HOST_ATTR) :
        meta.styles;
    const strings = styleValues.map(str => constantPool.getConstLiteral(o.literal(str)));
    definitionMap.set('styles', o.literalArr(strings));
  } else if (meta.encapsulation === core.ViewEncapsulation.Emulated) {
    // If there is no style, don't generate css selectors on elements
    meta.encapsulation = core.ViewEncapsulation.None;
  }

  // Only set view encapsulation if it's not the default value
  if (meta.encapsulation !== core.ViewEncapsulation.Emulated) {
    definitionMap.set('encapsulation', o.literal(meta.encapsulation));
  }

  // e.g. `animation: [trigger('123', [])]`
  if (meta.animations !== null) {
    definitionMap.set(
        'data', o.literalMap([{key: 'animation', value: meta.animations, quoted: false}]));
  }

  // Only set the change detection flag if it's defined and it's not the default.
  if (changeDetection != null && changeDetection !== core.ChangeDetectionStrategy.Default) {
    definitionMap.set('changeDetection', o.literal(changeDetection));
  }

  const expression = o.importExpr(R3.defineComponent).callFn([definitionMap.toLiteralMap()]);

  const typeParams = createDirectiveTypeParams(meta);
  typeParams.push(stringArrayAsType(meta.template.ngContentSelectors));
  const type = o.expressionType(o.importExpr(R3.ComponentDefWithMeta, typeParams));

  return {expression, type};
}


/**
 * A wrapper around `compileDirective` which depends on render2 global analysis data as its input
 * instead of the `R3DirectiveMetadata`.
 *
 * `R3DirectiveMetadata` is computed from `CompileDirectiveMetadata` and other statically reflected
 * information.
 */
export function compileDirectiveFromRender2(
    outputCtx: OutputContext, directive: CompileDirectiveMetadata, reflector: CompileReflector,
    bindingParser: BindingParser) {
  const name = identifierName(directive.type)!;
  name || error(`Cannot resolver the name of ${directive.type}`);

  const definitionField = outputCtx.constantPool.propertyNameOf(DefinitionKind.Directive);

  const meta = directiveMetadataFromGlobalMetadata(directive, outputCtx, reflector);
  const res = compileDirectiveFromMetadata(meta, outputCtx.constantPool, bindingParser);
  const factoryRes = compileFactoryFunction(
      {...meta, injectFn: R3.directiveInject, target: R3FactoryTarget.Directive});
  const ngFactoryDefStatement = new o.ClassStmt(
      name, null,
      [new o.ClassField('ɵfac', o.INFERRED_TYPE, [o.StmtModifier.Static], factoryRes.factory)], [],
      new o.ClassMethod(null, [], []), []);
  const directiveDefStatement = new o.ClassStmt(
      name, null,
      [new o.ClassField(definitionField, o.INFERRED_TYPE, [o.StmtModifier.Static], res.expression)],
      [], new o.ClassMethod(null, [], []), []);

  // Create the partial class to be merged with the actual class.
  outputCtx.statements.push(ngFactoryDefStatement, directiveDefStatement);
}


/**
 * A wrapper around `compileComponent` which depends on render2 global analysis data as its input
 * instead of the `R3DirectiveMetadata`.
 *
 * `R3ComponentMetadata` is computed from `CompileDirectiveMetadata` and other statically reflected
 * information.
 */
export function compileComponentFromRender2(
    outputCtx: OutputContext, component: CompileDirectiveMetadata, render3Ast: Render3ParseResult,
    reflector: CompileReflector, bindingParser: BindingParser, directiveTypeBySel: Map<string, any>,
    pipeTypeByName: Map<string, any>) {
  const name = identifierName(component.type)!;
  name || error(`Cannot resolver the name of ${component.type}`);

  const definitionField = outputCtx.constantPool.propertyNameOf(DefinitionKind.Component);

  const summary = component.toSummary();

  // Compute the R3ComponentMetadata from the CompileDirectiveMetadata
  const meta: R3ComponentMetadata = {
    ...directiveMetadataFromGlobalMetadata(component, outputCtx, reflector),
    selector: component.selector,
    template: {nodes: render3Ast.nodes, ngContentSelectors: render3Ast.ngContentSelectors},
    directives: [],
    pipes: typeMapToExpressionMap(pipeTypeByName, outputCtx),
    viewQueries: queriesFromGlobalMetadata(component.viewQueries, outputCtx),
    wrapDirectivesAndPipesInClosure: false,
    styles: (summary.template && summary.template.styles) || EMPTY_ARRAY,
    encapsulation:
        (summary.template && summary.template.encapsulation) || core.ViewEncapsulation.Emulated,
    interpolation: DEFAULT_INTERPOLATION_CONFIG,
    animations: null,
    viewProviders:
        component.viewProviders.length > 0 ? new o.WrappedNodeExpr(component.viewProviders) : null,
    relativeContextFilePath: '',
    i18nUseExternalIds: true,
  };
  const res = compileComponentFromMetadata(meta, outputCtx.constantPool, bindingParser);
  const factoryRes = compileFactoryFunction(
      {...meta, injectFn: R3.directiveInject, target: R3FactoryTarget.Directive});
  const ngFactoryDefStatement = new o.ClassStmt(
      name, null,
      [new o.ClassField('ɵfac', o.INFERRED_TYPE, [o.StmtModifier.Static], factoryRes.factory)], [],
      new o.ClassMethod(null, [], []), []);
  const componentDefStatement = new o.ClassStmt(
      name, null,
      [new o.ClassField(definitionField, o.INFERRED_TYPE, [o.StmtModifier.Static], res.expression)],
      [], new o.ClassMethod(null, [], []), []);

  // Create the partial class to be merged with the actual class.
  outputCtx.statements.push(ngFactoryDefStatement, componentDefStatement);
}


/**
 * Compute `R3DirectiveMetadata` given `CompileDirectiveMetadata` and a `CompileReflector`.
 */
function directiveMetadataFromGlobalMetadata(
    directive: CompileDirectiveMetadata, outputCtx: OutputContext,
    reflector: CompileReflector): R3DirectiveMetadata {
  // The global-analysis based Ivy mode in ngc is no longer utilized/supported.
  throw new Error('unsupported');
}


/**
 * Convert `CompileQueryMetadata` into `R3QueryMetadata`.
 */
function queriesFromGlobalMetadata(
    queries: CompileQueryMetadata[], outputCtx: OutputContext): R3QueryMetadata[] {
  return queries.map(query => {
    let read: o.Expression|null = null;
    if (query.read && query.read.identifier) {
      read = outputCtx.importExpr(query.read.identifier.reference);
    }
    return {
      propertyName: query.propertyName,
      first: query.first,
      predicate: selectorsFromGlobalMetadata(query.selectors, outputCtx),
      descendants: query.descendants,
      read,
      static: !!query.static
    };
  });
}


/**
 * Convert `CompileTokenMetadata` for query selectors into either an expression for a predicate
 * type, or a list of string predicates.
 */
function selectorsFromGlobalMetadata(
    selectors: CompileTokenMetadata[], outputCtx: OutputContext): o.Expression|string[] {
  if (selectors.length > 1 || (selectors.length == 1 && selectors[0].value)) {
    const selectorStrings = selectors.map(value => value.value as string);
    selectorStrings.some(value => !value) &&
        error('Found a type among the string selectors expected');
    return outputCtx.constantPool.getConstLiteral(
        o.literalArr(selectorStrings.map(value => o.literal(value))));
  }

  if (selectors.length == 1) {
    const first = selectors[0];
    if (first.identifier) {
      return outputCtx.importExpr(first.identifier.reference);
    }
  }

  error('Unexpected query form');
  return o.NULL_EXPR;
}


function prepareQueryParams(query: R3QueryMetadata, constantPool: ConstantPool): o.Expression[] {
  const parameters = [getQueryPredicate(query, constantPool), o.literal(query.descendants)];
  if (query.read) {
    parameters.push(query.read);
  }
  return parameters;
}


function convertAttributesToExpressions(attributes: {[name: string]: o.Expression}):
    o.Expression[] {
  const values: o.Expression[] = [];
  for (let key of Object.getOwnPropertyNames(attributes)) {
    const value = attributes[key];
    values.push(o.literal(key), value);
  }
  return values;
}


// Define and update any content queries
function createContentQueriesFunction(
    queries: R3QueryMetadata[], constantPool: ConstantPool, name?: string): o.Expression {
  const createStatements: o.Statement[] = [];
  const updateStatements: o.Statement[] = [];
  const tempAllocator = temporaryAllocator(updateStatements, TEMPORARY_NAME);

  for (const query of queries) {
    const queryInstruction = query.static ? R3.staticContentQuery : R3.contentQuery;

    // creation, e.g. r3.contentQuery(dirIndex, somePredicate, true, null);
    createStatements.push(
        o.importExpr(queryInstruction)
            .callFn([o.variable('dirIndex'), ...prepareQueryParams(query, constantPool) as any])
            .toStmt());

    // update, e.g. (r3.queryRefresh(tmp = r3.loadQuery()) && (ctx.someDir = tmp));
    const temporary = tempAllocator();
    const getQueryList = o.importExpr(R3.loadQuery).callFn([]);
    const refresh = o.importExpr(R3.queryRefresh).callFn([temporary.set(getQueryList)]);
    const updateDirective = o.variable(CONTEXT_NAME)
                                .prop(query.propertyName)
                                .set(query.first ? temporary.prop('first') : temporary);
    updateStatements.push(refresh.and(updateDirective).toStmt());
  }

  const contentQueriesFnName = name ? `${name}_ContentQueries` : null;
  return o.fn(
      [
        new o.FnParam(RENDER_FLAGS, o.NUMBER_TYPE), new o.FnParam(CONTEXT_NAME, null),
        new o.FnParam('dirIndex', null)
      ],
      [
        renderFlagCheckIfStmt(core.RenderFlags.Create, createStatements),
        renderFlagCheckIfStmt(core.RenderFlags.Update, updateStatements)
      ],
      o.INFERRED_TYPE, null, contentQueriesFnName);
}


function stringAsType(str: string): o.Type {
  return o.expressionType(o.literal(str));
}


function stringMapAsType(map: {[key: string]: string|string[]}): o.Type {
  const mapValues = Object.keys(map).map(key => {
    const value = Array.isArray(map[key]) ? map[key][0] : map[key];
    return {
      key,
      value: o.literal(value),
      quoted: true,
    };
  });
  return o.expressionType(o.literalMap(mapValues));
}


function stringArrayAsType(arr: ReadonlyArray<string|null>): o.Type {
  return arr.length > 0 ? o.expressionType(o.literalArr(arr.map(value => o.literal(value)))) :
                          o.NONE_TYPE;
}


function createDirectiveTypeParams(meta: R3DirectiveMetadata): o.Type[] {
  // On the type side, remove newlines from the selector as it will need to fit into a TypeScript
  // string literal, which must be on one line.
  const selectorForType = meta.selector !== null ? meta.selector.replace(/\n/g, '') : null;

  return [
    typeWithParameters(meta.type.type, meta.typeArgumentCount),
    selectorForType !== null ? stringAsType(selectorForType) : o.NONE_TYPE,
    meta.exportAs !== null ? stringArrayAsType(meta.exportAs) : o.NONE_TYPE,
    stringMapAsType(meta.inputs),
    stringMapAsType(meta.outputs),
    stringArrayAsType(meta.queries.map(q => q.propertyName)),
  ];
}


// Define and update any view queries
function createViewQueriesFunction(
    viewQueries: R3QueryMetadata[], constantPool: ConstantPool, name?: string): o.Expression {
  const createStatements: o.Statement[] = [];
  const updateStatements: o.Statement[] = [];
  const tempAllocator = temporaryAllocator(updateStatements, TEMPORARY_NAME);

  viewQueries.forEach((query: R3QueryMetadata) => {
    const queryInstruction = query.static ? R3.staticViewQuery : R3.viewQuery;

    // creation, e.g. r3.viewQuery(somePredicate, true);
    const queryDefinition =
        o.importExpr(queryInstruction).callFn(prepareQueryParams(query, constantPool));
    createStatements.push(queryDefinition.toStmt());

    // update, e.g. (r3.queryRefresh(tmp = r3.loadQuery()) && (ctx.someDir = tmp));
    const temporary = tempAllocator();
    const getQueryList = o.importExpr(R3.loadQuery).callFn([]);
    const refresh = o.importExpr(R3.queryRefresh).callFn([temporary.set(getQueryList)]);
    const updateDirective = o.variable(CONTEXT_NAME)
                                .prop(query.propertyName)
                                .set(query.first ? temporary.prop('first') : temporary);
    updateStatements.push(refresh.and(updateDirective).toStmt());
  });

  const viewQueryFnName = name ? `${name}_Query` : null;
  return o.fn(
      [new o.FnParam(RENDER_FLAGS, o.NUMBER_TYPE), new o.FnParam(CONTEXT_NAME, null)],
      [
        renderFlagCheckIfStmt(core.RenderFlags.Create, createStatements),
        renderFlagCheckIfStmt(core.RenderFlags.Update, updateStatements)
      ],
      o.INFERRED_TYPE, null, viewQueryFnName);
}


// Return a host binding function or null if one is not necessary.
function createHostBindingsFunction(
    hostBindingsMetadata: R3HostMetadata, typeSourceSpan: ParseSourceSpan,
    bindingParser: BindingParser, constantPool: ConstantPool, selector: string, name: string,
    definitionMap: DefinitionMap): o.Expression|null {
  const bindingContext = o.variable(CONTEXT_NAME);
  const styleBuilder = new StylingBuilder(bindingContext);

  const {styleAttr, classAttr} = hostBindingsMetadata.specialAttributes;
  if (styleAttr !== undefined) {
    styleBuilder.registerStyleAttr(styleAttr);
  }
  if (classAttr !== undefined) {
    styleBuilder.registerClassAttr(classAttr);
  }

  const createStatements: o.Statement[] = [];
  const updateStatements: o.Statement[] = [];

  const hostBindingSourceSpan = typeSourceSpan;
  const directiveSummary = metadataAsSummary(hostBindingsMetadata);

  // Calculate host event bindings
  const eventBindings =
      bindingParser.createDirectiveHostEventAsts(directiveSummary, hostBindingSourceSpan);
  if (eventBindings && eventBindings.length) {
    const listeners = createHostListeners(eventBindings, name);
    createStatements.push(...listeners);
  }

  // Calculate the host property bindings
  const bindings = bindingParser.createBoundHostProperties(directiveSummary, hostBindingSourceSpan);
  const allOtherBindings: ParsedProperty[] = [];

  // We need to calculate the total amount of binding slots required by
  // all the instructions together before any value conversions happen.
  // Value conversions may require additional slots for interpolation and
  // bindings with pipes. These calculates happen after this block.
  let totalHostVarsCount = 0;
  bindings && bindings.forEach((binding: ParsedProperty) => {
    const stylingInputWasSet = styleBuilder.registerInputBasedOnName(
        binding.name, binding.expression, hostBindingSourceSpan);
    if (stylingInputWasSet) {
      totalHostVarsCount += MIN_STYLING_BINDING_SLOTS_REQUIRED;
    } else {
      allOtherBindings.push(binding);
      totalHostVarsCount++;
    }
  });

  let valueConverter: ValueConverter;
  const getValueConverter = () => {
    if (!valueConverter) {
      const hostVarsCountFn = (numSlots: number): number => {
        const originalVarsCount = totalHostVarsCount;
        totalHostVarsCount += numSlots;
        return originalVarsCount;
      };
      valueConverter = new ValueConverter(
          constantPool,
          () => error('Unexpected node'),  // new nodes are illegal here
          hostVarsCountFn,
          () => error('Unexpected pipe'));  // pipes are illegal here
    }
    return valueConverter;
  };

  const propertyBindings: o.Expression[][] = [];
  const attributeBindings: o.Expression[][] = [];
  const syntheticHostBindings: o.Expression[][] = [];
  allOtherBindings.forEach((binding: ParsedProperty) => {
    // resolve literal arrays and literal objects
    const value = binding.expression.visit(getValueConverter());
    const bindingExpr = bindingFn(bindingContext, value);

    const {bindingName, instruction, isAttribute} = getBindingNameAndInstruction(binding);

    const securityContexts =
        bindingParser.calcPossibleSecurityContexts(selector, bindingName, isAttribute)
            .filter(context => context !== core.SecurityContext.NONE);

    let sanitizerFn: o.ExternalExpr|null = null;
    if (securityContexts.length) {
      if (securityContexts.length === 2 &&
          securityContexts.indexOf(core.SecurityContext.URL) > -1 &&
          securityContexts.indexOf(core.SecurityContext.RESOURCE_URL) > -1) {
        // Special case for some URL attributes (such as "src" and "href") that may be a part
        // of different security contexts. In this case we use special santitization function and
        // select the actual sanitizer at runtime based on a tag name that is provided while
        // invoking sanitization function.
        sanitizerFn = o.importExpr(R3.sanitizeUrlOrResourceUrl);
      } else {
        sanitizerFn = resolveSanitizationFn(securityContexts[0], isAttribute);
      }
    }
    const instructionParams = [o.literal(bindingName), bindingExpr.currValExpr];
    if (sanitizerFn) {
      instructionParams.push(sanitizerFn);
    }

    updateStatements.push(...bindingExpr.stmts);

    if (instruction === R3.hostProperty) {
      propertyBindings.push(instructionParams);
    } else if (instruction === R3.attribute) {
      attributeBindings.push(instructionParams);
    } else if (instruction === R3.syntheticHostProperty) {
      syntheticHostBindings.push(instructionParams);
    } else {
      updateStatements.push(o.importExpr(instruction).callFn(instructionParams).toStmt());
    }
  });

  if (propertyBindings.length > 0) {
    updateStatements.push(chainedInstruction(R3.hostProperty, propertyBindings).toStmt());
  }

  if (attributeBindings.length > 0) {
    updateStatements.push(chainedInstruction(R3.attribute, attributeBindings).toStmt());
  }

  if (syntheticHostBindings.length > 0) {
    updateStatements.push(
        chainedInstruction(R3.syntheticHostProperty, syntheticHostBindings).toStmt());
  }

  // since we're dealing with directives/components and both have hostBinding
  // functions, we need to generate a special hostAttrs instruction that deals
  // with both the assignment of styling as well as static attributes to the host
  // element. The instruction below will instruct all initial styling (styling
  // that is inside of a host binding within a directive/component) to be attached
  // to the host element alongside any of the provided host attributes that were
  // collected earlier.
  const hostAttrs = convertAttributesToExpressions(hostBindingsMetadata.attributes);
  styleBuilder.assignHostAttrs(hostAttrs, definitionMap);

  if (styleBuilder.hasBindings) {
    // finally each binding that was registered in the statement above will need to be added to
    // the update block of a component/directive templateFn/hostBindingsFn so that the bindings
    // are evaluated and updated for the element.
    styleBuilder.buildUpdateLevelInstructions(getValueConverter()).forEach(instruction => {
      if (instruction.calls.length > 0) {
        const calls: o.Expression[][] = [];

        instruction.calls.forEach(call => {
          // we subtract a value of `1` here because the binding slot was already allocated
          // at the top of this method when all the input bindings were counted.
          totalHostVarsCount +=
              Math.max(call.allocateBindingSlots - MIN_STYLING_BINDING_SLOTS_REQUIRED, 0);
          calls.push(convertStylingCall(call, bindingContext, bindingFn));
        });

        updateStatements.push(chainedInstruction(instruction.reference, calls).toStmt());
      }
    });
  }

  if (totalHostVarsCount) {
    definitionMap.set('hostVars', o.literal(totalHostVarsCount));
  }

  if (createStatements.length > 0 || updateStatements.length > 0) {
    const hostBindingsFnName = name ? `${name}_HostBindings` : null;
    const statements: o.Statement[] = [];
    if (createStatements.length > 0) {
      statements.push(renderFlagCheckIfStmt(core.RenderFlags.Create, createStatements));
    }
    if (updateStatements.length > 0) {
      statements.push(renderFlagCheckIfStmt(core.RenderFlags.Update, updateStatements));
    }
    return o.fn(
        [new o.FnParam(RENDER_FLAGS, o.NUMBER_TYPE), new o.FnParam(CONTEXT_NAME, null)], statements,
        o.INFERRED_TYPE, null, hostBindingsFnName);
  }

  return null;
}


function bindingFn(implicit: any, value: AST) {
  return convertPropertyBinding(
      null, implicit, value, 'b', BindingForm.Expression, () => error('Unexpected interpolation'));
}


function convertStylingCall(
    call: StylingInstructionCall, bindingContext: any, bindingFn: Function) {
  return call.params(value => bindingFn(bindingContext, value).currValExpr);
}


function getBindingNameAndInstruction(binding: ParsedProperty):
    {bindingName: string, instruction: o.ExternalReference, isAttribute: boolean} {
  let bindingName = binding.name;
  let instruction!: o.ExternalReference;

  // Check to see if this is an attr binding or a property binding
  const attrMatches = bindingName.match(ATTR_REGEX);
  if (attrMatches) {
    bindingName = attrMatches[1];
    instruction = R3.attribute;
  } else {
    if (binding.isAnimation) {
      bindingName = prepareSyntheticPropertyName(bindingName);
      // host bindings that have a synthetic property (e.g. @foo) should always be rendered
      // in the context of the component and not the parent. Therefore there is a special
      // compatibility instruction available for this purpose.
      instruction = R3.syntheticHostProperty;
    } else {
      instruction = R3.hostProperty;
    }
  }

  return {bindingName, instruction, isAttribute: !!attrMatches};
}


function createHostListeners(eventBindings: ParsedEvent[], name?: string): o.Statement[] {
  const listeners: o.Expression[][] = [];
  const syntheticListeners: o.Expression[][] = [];
  const instructions: o.Statement[] = [];

  eventBindings.forEach(binding => {
    let bindingName = binding.name && sanitizeIdentifier(binding.name);
    const bindingFnName = binding.type === ParsedEventType.Animation ?
        prepareSyntheticListenerFunctionName(bindingName, binding.targetOrPhase) :
        bindingName;
    const handlerName = name && bindingName ? `${name}_${bindingFnName}_HostBindingHandler` : null;
    const params = prepareEventListenerParameters(BoundEvent.fromParsedEvent(binding), handlerName);

    if (binding.type == ParsedEventType.Animation) {
      syntheticListeners.push(params);
    } else {
      listeners.push(params);
    }
  });

  if (syntheticListeners.length > 0) {
    instructions.push(chainedInstruction(R3.syntheticHostListener, syntheticListeners).toStmt());
  }

  if (listeners.length > 0) {
    instructions.push(chainedInstruction(R3.listener, listeners).toStmt());
  }

  return instructions;
}


function metadataAsSummary(meta: R3HostMetadata): CompileDirectiveSummary {
  // clang-format off
  return {
    // This is used by the BindingParser, which only deals with listeners and properties. There's no
    // need to pass attributes to it.
    hostAttributes: {},
    hostListeners: meta.listeners,
    hostProperties: meta.properties,
  } as CompileDirectiveSummary;
  // clang-format on
}


function typeMapToExpressionMap(
    map: Map<string, StaticSymbol>, outputCtx: OutputContext): Map<string, o.Expression> {
  // Convert each map entry into another entry where the value is an expression importing the type.
  const entries = Array.from(map).map(
      ([key, type]): [string, o.Expression] => [key, outputCtx.importExpr(type)]);
  return new Map(entries);
}


export function parseHostBindings(host: {[key: string]: string|o.Expression}): ParsedHostBindings {
  const attributes: {[key: string]: o.Expression} = {};
  const listeners: {[key: string]: string} = {};
  const properties: {[key: string]: string} = {};
  const specialAttributes: {styleAttr?: string; classAttr?: string;} = {};

  for (const key of Object.keys(host)) {
    const value = host[key];
    const matches = key.match(HOST_REG_EXP);

    if (matches === null) {
      switch (key) {
        case 'class':
          if (typeof value !== 'string') {
            // TODO(alxhub): make this a diagnostic.
            throw new Error(`Class binding must be string`);
          }
          specialAttributes.classAttr = value;
          break;
        case 'style':
          if (typeof value !== 'string') {
            // TODO(alxhub): make this a diagnostic.
            throw new Error(`Style binding must be string`);
          }
          specialAttributes.styleAttr = value;
          break;
        default:
          if (typeof value === 'string') {
            attributes[key] = o.literal(value);
          } else {
            attributes[key] = value;
          }
      }
    } else if (matches[HostBindingGroup.Binding] != null) {
      if (typeof value !== 'string') {
        // TODO(alxhub): make this a diagnostic.
        throw new Error(`Property binding must be string`);
      }
      // synthetic properties (the ones that have a `@` as a prefix)
      // are still treated the same as regular properties. Therefore
      // there is no point in storing them in a separate map.
      properties[matches[HostBindingGroup.Binding]] = value;
    } else if (matches[HostBindingGroup.Event] != null) {
      if (typeof value !== 'string') {
        // TODO(alxhub): make this a diagnostic.
        throw new Error(`Event binding must be string`);
      }
      listeners[matches[HostBindingGroup.Event]] = value;
    }
  }

  return {attributes, listeners, properties, specialAttributes};
}


/**
 * Verifies host bindings and returns the list of errors (if any). Empty array indicates that a
 * given set of host bindings has no errors.
 *
 * @param bindings set of host bindings to verify.
 * @param sourceSpan source span where host bindings were defined.
 * @returns array of errors associated with a given set of host bindings.
 */
export function verifyHostBindings(
    bindings: ParsedHostBindings, sourceSpan: ParseSourceSpan): ParseError[] {
  const summary = metadataAsSummary(bindings);
  // TODO: abstract out host bindings verification logic and use it instead of
  // creating events and properties ASTs to detect errors (FW-996)
  const bindingParser = makeBindingParser();
  bindingParser.createDirectiveHostEventAsts(summary, sourceSpan);
  bindingParser.createBoundHostProperties(summary, sourceSpan);
  return bindingParser.errors;
}


function compileStyles(styles: string[], selector: string, hostSelector: string): string[] {
  const shadowCss = new ShadowCss();
  return styles.map(style => {
    return shadowCss!.shimCssText(style, selector, hostSelector);
  });
}


e => o.literal(e)


value => value != null ? o.literal(value) : o.literal(undefined)


str => constantPool.getConstLiteral(o.literal(str))


query => {
    let read: o.Expression|null = null;
    if (query.read && query.read.identifier) {
      read = outputCtx.importExpr(query.read.identifier.reference);
    }
    return {
      propertyName: query.propertyName,
      first: query.first,
      predicate: selectorsFromGlobalMetadata(query.selectors, outputCtx),
      descendants: query.descendants,
      read,
      static: !!query.static
    };
  }


value => value.value as string


value => !value


value => o.literal(value)


key => {
    const value = Array.isArray(map[key]) ? map[key][0] : map[key];
    return {
      key,
      value: o.literal(value),
      quoted: true,
    };
  }


q => q.propertyName


(query: R3QueryMetadata) => {
    const queryInstruction = query.static ? R3.staticViewQuery : R3.viewQuery;

    // creation, e.g. r3.viewQuery(somePredicate, true);
    const queryDefinition =
        o.importExpr(queryInstruction).callFn(prepareQueryParams(query, constantPool));
    createStatements.push(queryDefinition.toStmt());

    // update, e.g. (r3.queryRefresh(tmp = r3.loadQuery()) && (ctx.someDir = tmp));
    const temporary = tempAllocator();
    const getQueryList = o.importExpr(R3.loadQuery).callFn([]);
    const refresh = o.importExpr(R3.queryRefresh).callFn([temporary.set(getQueryList)]);
    const updateDirective = o.variable(CONTEXT_NAME)
                                .prop(query.propertyName)
                                .set(query.first ? temporary.prop('first') : temporary);
    updateStatements.push(refresh.and(updateDirective).toStmt());
  }


(binding: ParsedProperty) => {
    const stylingInputWasSet = styleBuilder.registerInputBasedOnName(
        binding.name, binding.expression, hostBindingSourceSpan);
    if (stylingInputWasSet) {
      totalHostVarsCount += MIN_STYLING_BINDING_SLOTS_REQUIRED;
    } else {
      allOtherBindings.push(binding);
      totalHostVarsCount++;
    }
  }


() => {
    if (!valueConverter) {
      const hostVarsCountFn = (numSlots: number): number => {
        const originalVarsCount = totalHostVarsCount;
        totalHostVarsCount += numSlots;
        return originalVarsCount;
      };
      valueConverter = new ValueConverter(
          constantPool,
          () => error('Unexpected node'),  // new nodes are illegal here
          hostVarsCountFn,
          () => error('Unexpected pipe'));  // pipes are illegal here
    }
    return valueConverter;
  }


(numSlots: number): number => {
        const originalVarsCount = totalHostVarsCount;
        totalHostVarsCount += numSlots;
        return originalVarsCount;
      }


() => error('Unexpected node')


() => error('Unexpected pipe')


(binding: ParsedProperty) => {
    // resolve literal arrays and literal objects
    const value = binding.expression.visit(getValueConverter());
    const bindingExpr = bindingFn(bindingContext, value);

    const {bindingName, instruction, isAttribute} = getBindingNameAndInstruction(binding);

    const securityContexts =
        bindingParser.calcPossibleSecurityContexts(selector, bindingName, isAttribute)
            .filter(context => context !== core.SecurityContext.NONE);

    let sanitizerFn: o.ExternalExpr|null = null;
    if (securityContexts.length) {
      if (securityContexts.length === 2 &&
          securityContexts.indexOf(core.SecurityContext.URL) > -1 &&
          securityContexts.indexOf(core.SecurityContext.RESOURCE_URL) > -1) {
        // Special case for some URL attributes (such as "src" and "href") that may be a part
        // of different security contexts. In this case we use special santitization function and
        // select the actual sanitizer at runtime based on a tag name that is provided while
        // invoking sanitization function.
        sanitizerFn = o.importExpr(R3.sanitizeUrlOrResourceUrl);
      } else {
        sanitizerFn = resolveSanitizationFn(securityContexts[0], isAttribute);
      }
    }
    const instructionParams = [o.literal(bindingName), bindingExpr.currValExpr];
    if (sanitizerFn) {
      instructionParams.push(sanitizerFn);
    }

    updateStatements.push(...bindingExpr.stmts);

    if (instruction === R3.hostProperty) {
      propertyBindings.push(instructionParams);
    } else if (instruction === R3.attribute) {
      attributeBindings.push(instructionParams);
    } else if (instruction === R3.syntheticHostProperty) {
      syntheticHostBindings.push(instructionParams);
    } else {
      updateStatements.push(o.importExpr(instruction).callFn(instructionParams).toStmt());
    }
  }


context => context !== core.SecurityContext.NONE


instruction => {
      if (instruction.calls.length > 0) {
        const calls: o.Expression[][] = [];

        instruction.calls.forEach(call => {
          // we subtract a value of `1` here because the binding slot was already allocated
          // at the top of this method when all the input bindings were counted.
          totalHostVarsCount +=
              Math.max(call.allocateBindingSlots - MIN_STYLING_BINDING_SLOTS_REQUIRED, 0);
          calls.push(convertStylingCall(call, bindingContext, bindingFn));
        });

        updateStatements.push(chainedInstruction(instruction.reference, calls).toStmt());
      }
    }


call => {
          // we subtract a value of `1` here because the binding slot was already allocated
          // at the top of this method when all the input bindings were counted.
          totalHostVarsCount +=
              Math.max(call.allocateBindingSlots - MIN_STYLING_BINDING_SLOTS_REQUIRED, 0);
          calls.push(convertStylingCall(call, bindingContext, bindingFn));
        }


() => error('Unexpected interpolation')


value => bindingFn(bindingContext, value).currValExpr


binding => {
    let bindingName = binding.name && sanitizeIdentifier(binding.name);
    const bindingFnName = binding.type === ParsedEventType.Animation ?
        prepareSyntheticListenerFunctionName(bindingName, binding.targetOrPhase) :
        bindingName;
    const handlerName = name && bindingName ? `${name}_${bindingFnName}_HostBindingHandler` : null;
    const params = prepareEventListenerParameters(BoundEvent.fromParsedEvent(binding), handlerName);

    if (binding.type == ParsedEventType.Animation) {
      syntheticListeners.push(params);
    } else {
      listeners.push(params);
    }
  }


([key, type]): [string, o.Expression] => [key, outputCtx.importExpr(type)]


style => {
    return shadowCss!.shimCssText(style, selector, hostSelector);
  }


// Defines Host Bindings structure that contains attributes, listeners, and properties,
// parsed from the `host` object defined for a Type.
export interface ParsedHostBindings {
  attributes: {[key: string]: o.Expression};
  listeners: {[key: string]: string};
  properties: {[key: string]: string};
  specialAttributes: {styleAttr?: string; classAttr?: string;};
}


// Represents the groups in the above regex.
const enum HostBindingGroup {
  // group 1: "prop" from "[prop]", or "attr.role" from "[attr.role]", or @anim from [@anim]
  Binding = 1,

  // group 2: "event" from "(event)"
  Event = 2,
}


@injectable()
export default class UpdateLogDischargePerformedService {
  constructor(
    @inject('LogsRepository')
    private logsRepository: ILogsRepository,
  ) {}

  public async execute({
    log_id,
    discharge_performed,
  }: IRequest): Promise<Log> {
    const log = await this.logsRepository.findById(log_id);

    if (!log) {
      throw new AppError('Log not found.');
    }

    merge(log, { discharge_performed });

    await this.logsRepository.save(log);

    return log;
  }
}


interface IRequest {
  log_id: string;
  discharge_performed: boolean;
}


public async execute({
    log_id,
    discharge_performed,
  }: IRequest): Promise<Log> {
    const log = await this.logsRepository.findById(log_id);

    if (!log) {
      throw new AppError('Log not found.');
    }

    merge(log, { discharge_performed });

    await this.logsRepository.save(log);

    return log;
  }


async function openDoor(day: number, senderKey) {
  const parts = contracts[day].split(".");
  if (mocknet && parts[0] === "ST12EY99GS4YKP0CP2CFW6SEPWQ2CGVRWK5GHKDRV") {
    parts[0] = "ST2ZRX0K27GW0SP3GJCEMHD95TQGJMKB7G9Y0X1MH";
  }
  const tx = await makeContractCall({
    contractAddress: calendarAddress,
    contractName: "advent-calendar",
    functionName: "open-door",
    functionArgs: [uintCV(day), contractPrincipalCV(parts[0], parts[1])],
    senderKey,
    network,
  });
  await handleTransaction(tx);
}


() => {
  it("should open door", async () => {
    await openDoor(
      8,
      "052cc5b8f25b1e44a65329244066f76c8057accd5316c889f476d0ea0329632c01" // replace with your key
    );
  });
}


async () => {
    await openDoor(
      8,
      "052cc5b8f25b1e44a65329244066f76c8057accd5316c889f476d0ea0329632c01" // replace with your key
    );
  }


function generateSessionId() {
  return uid(24);
}


function sessionStrategy<TSessionStrategy extends SessionStrategy<any>>(
  sessionStrategy: TSessionStrategy
): TSessionStrategy {
  return sessionStrategy;
}


/* TODO:
  - [ ] We could support additional where input to validate item sessions (e.g an isEnabled boolean)
*/
export function withItemData(createSession: CreateSession, fieldSelections: FieldSelections) {
  return (): SessionStrategy<any> => {
    const { get, ...sessionThing } = createSession();
    return {
      ...sessionThing,
      get: async ({ req, keystone }) => {
        const session = await get({ req, keystone });
        if (!session) return;
        // Only load data for lists specified in fieldSelections
        if (!fieldSelections[session.listKey]) return session;
        const context = await keystone.createContext({ skipAccessControl: true });
        const { gqlNames } = keystone.adminMeta.lists[session.listKey];
        const query = parse(`query($id: ID!) {
          item: ${gqlNames.itemQueryName}(where: { id: $id }) {
            ${fieldSelections[session.listKey]}
          }
        }`);
        const args = { id: session.itemId };
        const result = await execute(keystone.graphQLSchema, query, null, context, args);
        // TODO: This causes "not found" errors to throw, which is not what we want
        // TOOD: Also, why is this coming back as an access denied error instead of "not found" with an invalid session?
        // if (result.errors?.length) {
        //   throw result.errors[0];
        // }
        // If there is no matching item found, return no session
        if (!result?.data?.item) {
          return;
        }
        return { ...session, item: result.data.item };
      },
    };
  };
}


export function statelessSessions({
  secret,
  maxAge = MAX_AGE,
  path = '/',
  secure = process.env.NODE_ENV === 'production',
  ironOptions = Iron.defaults,
}: StatelessSessionsOptions) {
  return () => {
    if (secret.length < 32) {
      throw new Error('The session secret must be at least 32 characters long');
    }
    return sessionStrategy({
      // eslint-disable-next-line @typescript-eslint/no-unused-vars
      async get({ req, keystone }) {
        if (!req.headers.cookie) return;
        let cookies = cookie.parse(req.headers.cookie);
        if (!cookies[TOKEN_NAME]) return;
        try {
          return await Iron.unseal(cookies[TOKEN_NAME], secret, ironOptions);
        } catch (err) {}
      },
      async end({ res }) {
        res.setHeader(
          'Set-Cookie',
          cookie.serialize(TOKEN_NAME, '', {
            maxAge: 0,
            expires: new Date(),
            httpOnly: true,
            secure,
            path,
            sameSite: 'lax',
          })
        );
      },
      async start({ res, data }) {
        let sealedData = await Iron.seal(data, secret, { ...ironOptions, ttl: maxAge * 1000 });

        res.setHeader(
          'Set-Cookie',
          cookie.serialize(TOKEN_NAME, sealedData, {
            maxAge,
            expires: new Date(Date.now() + maxAge * 1000),
            httpOnly: true,
            secure,
            path,
            sameSite: 'lax',
          })
        );

        return sealedData;
      },
    });
  };
}


export function storedSessions({
  store: storeOption,
  maxAge = MAX_AGE,
  ...statelessSessionsOptions
}: {
  store: SessionStoreFunction;
} & StatelessSessionsOptions): () => SessionStrategy<JSONValue> {
  return () => {
    let { get, start, end } = statelessSessions({ ...statelessSessionsOptions, maxAge })();
    let store = typeof storeOption === 'function' ? storeOption({ maxAge }) : storeOption;
    return {
      connect: store.connect,
      disconnect: store.disconnect,
      async get({ req, keystone }) {
        let sessionId = await get({ req, keystone });
        if (typeof sessionId === 'string') {
          return store.get(sessionId);
        }
      },
      async start({ res, data, keystone }) {
        let sessionId = generateSessionId();
        await store.set(sessionId, data);
        return start({ res, data: { sessionId }, keystone });
      },
      async end({ req, res, keystone }) {
        let sessionId = await get({ req, keystone });
        if (typeof sessionId === 'string') {
          await store.delete(sessionId);
        }
        await end({ req, res, keystone });
      },
    };
  };
}


export function sessionStuff(sessionStrategy: SessionStrategy<unknown>) {
  let isConnected = false;
  let connect = async () => {
    await sessionStrategy.connect?.();
    isConnected = true;
  };
  let disconnect = async () => {
    await sessionStrategy.disconnect?.();
    isConnected = false;
  };
  return {
    connect,
    disconnect,
    async createContext(
      req: IncomingMessage,
      res: ServerResponse,
      keystone: Keystone
    ): Promise<SessionContext> {
      if (!isConnected) {
        await connect();
      }
      const session = await sessionStrategy.get({ req, keystone });
      const startSession = sessionStrategy.start;
      const endSession = sessionStrategy.end;
      return {
        session,
        startSession: startSession
          ? (data: unknown) => {
              return startSession({ res, data, keystone });
            }
          : undefined,
        endSession: endSession
          ? () => {
              return endSession({ req, res, keystone });
            }
          : undefined,
      };
    },
  };
}


(): SessionStrategy<any> => {
    const { get, ...sessionThing } = createSession();
    return {
      ...sessionThing,
      get: async ({ req, keystone }) => {
        const session = await get({ req, keystone });
        if (!session) return;
        // Only load data for lists specified in fieldSelections
        if (!fieldSelections[session.listKey]) return session;
        const context = await keystone.createContext({ skipAccessControl: true });
        const { gqlNames } = keystone.adminMeta.lists[session.listKey];
        const query = parse(`query($id: ID!) {
          item: ${gqlNames.itemQueryName}(where: { id: $id }) {
            ${fieldSelections[session.listKey]}
          }
        }`);
        const args = { id: session.itemId };
        const result = await execute(keystone.graphQLSchema, query, null, context, args);
        // TODO: This causes "not found" errors to throw, which is not what we want
        // TOOD: Also, why is this coming back as an access denied error instead of "not found" with an invalid session?
        // if (result.errors?.length) {
        //   throw result.errors[0];
        // }
        // If there is no matching item found, return no session
        if (!result?.data?.item) {
          return;
        }
        return { ...session, item: result.data.item };
      },
    };
  }


async ({ req, keystone }) => {
        const session = await get({ req, keystone });
        if (!session) return;
        // Only load data for lists specified in fieldSelections
        if (!fieldSelections[session.listKey]) return session;
        const context = await keystone.createContext({ skipAccessControl: true });
        const { gqlNames } = keystone.adminMeta.lists[session.listKey];
        const query = parse(`query($id: ID!) {
          item: ${gqlNames.itemQueryName}(where: { id: $id }) {
            ${fieldSelections[session.listKey]}
          }
        }`);
        const args = { id: session.itemId };
        const result = await execute(keystone.graphQLSchema, query, null, context, args);
        // TODO: This causes "not found" errors to throw, which is not what we want
        // TOOD: Also, why is this coming back as an access denied error instead of "not found" with an invalid session?
        // if (result.errors?.length) {
        //   throw result.errors[0];
        // }
        // If there is no matching item found, return no session
        if (!result?.data?.item) {
          return;
        }
        return { ...session, item: result.data.item };
      }


() => {
    if (secret.length < 32) {
      throw new Error('The session secret must be at least 32 characters long');
    }
    return sessionStrategy({
      // eslint-disable-next-line @typescript-eslint/no-unused-vars
      async get({ req, keystone }) {
        if (!req.headers.cookie) return;
        let cookies = cookie.parse(req.headers.cookie);
        if (!cookies[TOKEN_NAME]) return;
        try {
          return await Iron.unseal(cookies[TOKEN_NAME], secret, ironOptions);
        } catch (err) {}
      },
      async end({ res }) {
        res.setHeader(
          'Set-Cookie',
          cookie.serialize(TOKEN_NAME, '', {
            maxAge: 0,
            expires: new Date(),
            httpOnly: true,
            secure,
            path,
            sameSite: 'lax',
          })
        );
      },
      async start({ res, data }) {
        let sealedData = await Iron.seal(data, secret, { ...ironOptions, ttl: maxAge * 1000 });

        res.setHeader(
          'Set-Cookie',
          cookie.serialize(TOKEN_NAME, sealedData, {
            maxAge,
            expires: new Date(Date.now() + maxAge * 1000),
            httpOnly: true,
            secure,
            path,
            sameSite: 'lax',
          })
        );

        return sealedData;
      },
    });
  }


() => {
    let { get, start, end } = statelessSessions({ ...statelessSessionsOptions, maxAge })();
    let store = typeof storeOption === 'function' ? storeOption({ maxAge }) : storeOption;
    return {
      connect: store.connect,
      disconnect: store.disconnect,
      async get({ req, keystone }) {
        let sessionId = await get({ req, keystone });
        if (typeof sessionId === 'string') {
          return store.get(sessionId);
        }
      },
      async start({ res, data, keystone }) {
        let sessionId = generateSessionId();
        await store.set(sessionId, data);
        return start({ res, data: { sessionId }, keystone });
      },
      async end({ req, res, keystone }) {
        let sessionId = await get({ req, keystone });
        if (typeof sessionId === 'string') {
          await store.delete(sessionId);
        }
        await end({ req, res, keystone });
      },
    };
  }


async () => {
    await sessionStrategy.connect?.();
    isConnected = true;
  }


async () => {
    await sessionStrategy.disconnect?.();
    isConnected = false;
  }


(data: unknown) => {
              return startSession({ res, data, keystone });
            }


() => {
              return endSession({ req, res, keystone });
            }


// should we also accept httpOnly?
type StatelessSessionsOptions = {
  /**
   * Secret used by https://github.com/hapijs/iron for encapsulating data. Must be at least 32 characters long
   */
  secret: string;
  /**
   * Iron seal options for customizing the key derivation algorithm used to generate encryption and integrity verification keys as well as the algorithms and salt sizes used.
   *
   * @default Iron.defaults
   */
  ironOptions?: Iron.SealOptions;
  /**
   * Specifies the number (in seconds) to be the value for the `Max-Age`
   * `Set-Cookie` attribute.
   *
   * @default 60 * 60 * 8 // 8 hours
   */
  maxAge?: number;
  /**
   * Specifies the boolean value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.5|`Secure` `Set-Cookie` attribute}.
   *
   * *Note* be careful when setting this to `true`, as compliant clients will
   * not send the cookie back to the server in the future if the browser does
   * not have an HTTPS connection.
   *
   * @default process.env.NODE_ENV === 'production'
   */
  secure?: boolean;
  /**
   * Specifies the value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.4|`Path` `Set-Cookie` attribute}.
   *
   * @default '/'
   */
  path?: string;
};


type FieldSelections = {
  [listKey: string]: string;
};


type CreateSession = ReturnType<typeof statelessSessions>;


// eslint-disable-next-line @typescript-eslint/no-unused-vars
async get({ req, keystone }) {
        if (!req.headers.cookie) return;
        let cookies = cookie.parse(req.headers.cookie);
        if (!cookies[TOKEN_NAME]) return;
        try {
          return await Iron.unseal(cookies[TOKEN_NAME], secret, ironOptions);
        } catch (err) {}
      }


async end({ res }) {
        res.setHeader(
          'Set-Cookie',
          cookie.serialize(TOKEN_NAME, '', {
            maxAge: 0,
            expires: new Date(),
            httpOnly: true,
            secure,
            path,
            sameSite: 'lax',
          })
        );
      }


async start({ res, data }) {
        let sealedData = await Iron.seal(data, secret, { ...ironOptions, ttl: maxAge * 1000 });

        res.setHeader(
          'Set-Cookie',
          cookie.serialize(TOKEN_NAME, sealedData, {
            maxAge,
            expires: new Date(Date.now() + maxAge * 1000),
            httpOnly: true,
            secure,
            path,
            sameSite: 'lax',
          })
        );

        return sealedData;
      }


async get({ req, keystone }) {
        let sessionId = await get({ req, keystone });
        if (typeof sessionId === 'string') {
          return store.get(sessionId);
        }
      }


async start({ res, data, keystone }) {
        let sessionId = generateSessionId();
        await store.set(sessionId, data);
        return start({ res, data: { sessionId }, keystone });
      }


async end({ req, res, keystone }) {
        let sessionId = await get({ req, keystone });
        if (typeof sessionId === 'string') {
          await store.delete(sessionId);
        }
        await end({ req, res, keystone });
      }


async createContext(
      req: IncomingMessage,
      res: ServerResponse,
      keystone: Keystone
    ): Promise<SessionContext> {
      if (!isConnected) {
        await connect();
      }
      const session = await sessionStrategy.get({ req, keystone });
      const startSession = sessionStrategy.start;
      const endSession = sessionStrategy.end;
      return {
        session,
        startSession: startSession
          ? (data: unknown) => {
              return startSession({ res, data, keystone });
            }
          : undefined,
        endSession: endSession
          ? () => {
              return endSession({ req, res, keystone });
            }
          : undefined,
      };
    }


function writeTypescriptConfig(packageRoot: string): void {
  const tsConfigJson = {
    extends: path.resolve(packageRoot, './tsconfig.json'),
    include: [path.resolve(packageRoot, './src')],
    compilerOptions: {
      downlevelIteration: true // Needed for FirebaseApp
    }
  };
  fs.writeFileSync(
    path.resolve(tmpDir, 'tsconfig.json'),
    JSON.stringify(tsConfigJson),
    { encoding: 'utf-8' }
  );
}


function writePackageJson(packageName: string): void {
  const packageJson = {
    'name': `@firebase/${packageName}`
  };
  const packageJsonPath = path.resolve(tmpDir, 'package.json');
  fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson), {
    encoding: 'utf-8'
  });
}


function loadApiExtractorConfig(
  typescriptDtsPath: string,
  rollupDtsPath: string,
  untrimmedRollupDtsPath: string,
  dtsRollupEnabled: boolean,
  apiReportEnabled: boolean
): ExtractorConfig {
  const apiExtractorJsonPath = path.resolve(tmpDir, 'api-extractor.json');
  const apiExtractorJson = {
    extends: baseApiExtractorConfigFile,
    mainEntryPointFilePath: typescriptDtsPath,
    'dtsRollup': {
      'enabled': dtsRollupEnabled,
      publicTrimmedFilePath: rollupDtsPath,
      untrimmedFilePath: untrimmedRollupDtsPath
    },
    'tsdocMetadata': {
      'enabled': false
    },
    'apiReport': {
      'enabled': apiReportEnabled,
      reportFolder
    },
    'messages': {
      'extractorMessageReporting': {
        'ae-missing-release-tag': {
          'logLevel': 'none'
        },
        'ae-unresolved-link': {
          'logLevel': 'none'
        },
        'ae-forgotten-export': {
          'logLevel': apiReportEnabled ? 'error' : 'none'
        }
      },
      'tsdocMessageReporting': {
        'tsdoc-undefined-tag': {
          'logLevel': 'none'
        }
      }
    }
  };
  fs.writeFileSync(apiExtractorJsonPath, JSON.stringify(apiExtractorJson), {
    encoding: 'utf-8'
  });
  console.log(apiExtractorJsonPath);
  return ExtractorConfig.loadFileAndPrepare(apiExtractorJsonPath);
}


/**
 * Generates the Public API from generated DTS files.
 *
 * @param packageName - The name of the Firebase package (e.g. "database" or
 * "firestore-lite")
 * @param packageRoot - The root path of the package
 * @param typescriptDtsPath - The .d.ts file generated by the Typescript
 * compiler as we transpile our sources
 * @param rollupDtsPath - A "bundled" version of our d.ts files that includes
 * all public and private types
 * @param untrimmedRollupDtsPath - A "bundled" version of our d.ts files that
 * includes all public and private types, but also include exports marked as
 * `@internal`. This file is used by compat APIs to use internal exports
 * @param publicDtsPath - The output file for the customer-facing .d.ts file
 * that only includes the public APIs
 */
export async function generateApi(
  packageName: string,
  packageRoot: string,
  typescriptDtsPath: string,
  rollupDtsPath: string,
  untrimmedRollupDtsPath: string,
  publicDtsPath: string
): Promise<void> {
  console.log(`Configuring API Extractor for #{packageName}`);
  writeTypescriptConfig(packageRoot);
  writePackageJson(packageName);

  let extractorConfig = loadApiExtractorConfig(
    typescriptDtsPath,
    rollupDtsPath,
    untrimmedRollupDtsPath,
    /* dtsRollupEnabled= */ true,
    /* apiReportEnabled= */ false
  );
  Extractor.invoke(extractorConfig, {
    localBuild: true
  });

  console.log('Generated rollup DTS');
  pruneDts(rollupDtsPath, publicDtsPath);
  console.log('Pruned DTS file');
  await addBlankLines(publicDtsPath);
  console.log('Added blank lines after imports');
  await removeUnusedImports(publicDtsPath);
  console.log('Removed unused imports');

  extractorConfig = loadApiExtractorConfig(
    publicDtsPath,
    rollupDtsPath,
    untrimmedRollupDtsPath,
    /* dtsRollupEnabled= */ false,
    /* apiReportEnabled= */ true
  );
  Extractor.invoke(extractorConfig, { localBuild: true });
  console.log(`API report for ${packageName} written to ${reportFolder}`);
}


() => {
  let page: AppPage;

  beforeEach(() => {
    page = new AppPage();
  });

  it('should display welcome message', () => {
    page.navigateTo();
    expect(page.getParagraphText()).toEqual('Welcome to entertainmentSystem!');
  });
}


() => {
    page.navigateTo();
    expect(page.getParagraphText()).toEqual('Welcome to entertainmentSystem!');
  }


@NgModule({
  declarations: [
    AppComponent,
    BadgeComponent,
    CardComponent,
    CardStackComponent,
    CardStackListComponent,
    ChatMessageComponent,
    ChatPaletteComponent,
    ChatTabComponent,
    ChatTabSettingComponent,
    ChatWindowComponent,
    ContextMenuComponent,
    FileSelecterComponent,
    FileStorageComponent,
    GameCharacterGeneratorComponent,
    GameCharacterSheetComponent,
    GameCharacterComponent,
    GameDataElementComponent,
    GameObjectInventoryComponent,
    GameTableMaskComponent,
    GameTableSettingComponent,
    GameTableComponent,
    JukeboxComponent,
    LobbyComponent,
    MegamiStorageComponent,
    ModalComponent,
    OverviewPanelComponent,
    PasswordCheckComponent,
    PeerMenuComponent,
    RoomSettingComponent,
    UIPanelComponent,
    SafePipe,
    ChatPaletteComponent,
    TextViewComponent,
    TerrainComponent,
    PeerCursorComponent,
    TextNoteComponent,
    MovableDirective,
    RotableDirective,
    NetworkIndicatorComponent,
    DiceSymbolComponent,
    TooltipDirective,
    DraggableDirective,
    ResizableDirective,
    ChatInputComponent,
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    CommonModule,
    FormsModule,
    ColorPickerModule
  ],
  providers: [
    AppConfigService,
    ChatMessageService,
    ContextMenuService,
    ModalService,
    GameObjectInventoryService,
    PanelService,
    PointerDeviceService,
    TabletopService,
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }


() => process.exit(0)


(error) => {
    console.error(error)
    process.exit(1)
  }


assert => {
    assert.equal(invocationCounts.testSkipped, undefined);
  }


assert => {
    assert.equal(invocationCounts.testNotSkipped, 1);
  }


@suite('(experiment) Test use of the @skip decorator')
class SkipTest {
  @test.skip
  testSkipped(assert: Assert) {
    assert.ok(true);
    invocationCounts.testSkipped = (invocationCounts.testSkipped || 0) + 1;
  }

  @test
  testNotSkipped(assert: Assert) {
    assert.ok(true);
    invocationCounts.testNotSkipped =
      (invocationCounts.testNotSkipped || 0) + 1;
  }
}


@test.skip
  testSkipped(assert: Assert) {
    assert.ok(true);
    invocationCounts.testSkipped = (invocationCounts.testSkipped || 0) + 1;
  }


@test
  testNotSkipped(assert: Assert) {
    assert.ok(true);
    invocationCounts.testNotSkipped =
      (invocationCounts.testNotSkipped || 0) + 1;
  }


function uploadBatchNormDownload(
      x: Float32Array, xTexShapeRowCol: [number, number], mean: Float32Array,
      meanTexShapeRowCol: [number, number], variance: Float32Array,
      varianceTexShapeRowCol: [number, number], offset: Float32Array|null,
      offsetTexShapeRowCol: [number, number]|null, scale: Float32Array|null,
      scaleTexShapeRowCol: [number, number]|null,
      varianceEpsilon: number): Float32Array {
    const resultTexShapeRC: [number, number] = xTexShapeRowCol;
    const gpgpu = new GPGPUContext();
    gpgpu.enableAutomaticDebugValidation(true);

    const shaderSource = batchnorm_gpu.getFragmentShaderSource(
        xTexShapeRowCol, meanTexShapeRowCol, varianceTexShapeRowCol,
        offsetTexShapeRowCol, scaleTexShapeRowCol, varianceEpsilon);

    const program = gpgpu.createProgram(shaderSource);

    const xTex =
        gpgpu.createMatrixTexture(xTexShapeRowCol[0], xTexShapeRowCol[1]);
    const meanTex =
        gpgpu.createMatrixTexture(meanTexShapeRowCol[0], meanTexShapeRowCol[1]);
    const varianceTex = gpgpu.createMatrixTexture(
        varianceTexShapeRowCol[0], varianceTexShapeRowCol[1]);

    let offsetTex = null;
    if (offset != null) {
      offsetTex = gpgpu.createMatrixTexture(
          offsetTexShapeRowCol![0], offsetTexShapeRowCol![1]);
    }
    let scaleTex = null;
    if (scale != null) {
      scaleTex = gpgpu.createMatrixTexture(
          scaleTexShapeRowCol![0], scaleTexShapeRowCol![1]);
    }

    const resultTex =
        gpgpu.createMatrixTexture(resultTexShapeRC[0], resultTexShapeRC[1]);

    gpgpu.uploadMatrixToTexture(
        xTex, xTexShapeRowCol[0], xTexShapeRowCol[1], x);
    gpgpu.uploadMatrixToTexture(
        meanTex, meanTexShapeRowCol[0], meanTexShapeRowCol[1], mean);
    gpgpu.uploadMatrixToTexture(
        varianceTex, varianceTexShapeRowCol[0], varianceTexShapeRowCol[1],
        variance);
    if (offset != null) {
      gpgpu.uploadMatrixToTexture(
          offsetTex!, offsetTexShapeRowCol![0], offsetTexShapeRowCol![1],
          offset);
    }
    if (scale != null) {
      gpgpu.uploadMatrixToTexture(
          scaleTex!, scaleTexShapeRowCol![0], scaleTexShapeRowCol![1], scale);
    }

    batchnorm_gpu.batchNormalization(
        gpgpu, program, xTex, xTexShapeRowCol, meanTex, meanTexShapeRowCol,
        varianceTex, varianceTexShapeRowCol, offsetTex, offsetTexShapeRowCol,
        scaleTex, scaleTexShapeRowCol, resultTex, resultTexShapeRC);

    const result = gpgpu.downloadMatrixFromTexture(
        resultTex, resultTexShapeRC[0], resultTexShapeRC[1]);

    gpgpu.deleteMatrixTexture(resultTex);
    gpgpu.deleteMatrixTexture(xTex);
    gpgpu.deleteMatrixTexture(meanTex);
    gpgpu.deleteMatrixTexture(varianceTex);
    if (offsetTex != null) {
      gpgpu.deleteMatrixTexture(offsetTex);
    }
    if (scaleTex != null) {
      gpgpu.deleteMatrixTexture(scaleTex);
    }
    gpgpu.deleteProgram(program);
    gpgpu.dispose();
    return result;
  }


() => {
    const x = new Float32Array([2, 100, 4, 400]);
    const mean = new Float32Array([1, 2]);
    const variance = new Float32Array([2, 3]);
    const varianceEpsilon = .001;

    const result = uploadBatchNormDownload(
        x, [2, 2], mean, [1, 2], variance, [1, 2], null, null, null, null,
        varianceEpsilon);

    const expectedResult = new Float32Array([
      (x[0] - mean[0]) * 1 / Math.sqrt(variance[0] + varianceEpsilon),
      (x[1] - mean[1]) * 1 / Math.sqrt(variance[1] + varianceEpsilon),
      (x[2] - mean[0]) * 1 / Math.sqrt(variance[0] + varianceEpsilon),
      (x[3] - mean[1]) * 1 / Math.sqrt(variance[1] + varianceEpsilon)
    ]);
    test_util.expectArraysClose(result, expectedResult, 1e-5);
  }


() => {
    const x = new Float32Array([2, 100, 4, 400]);
    const mean = new Float32Array([1, 2]);
    const variance = new Float32Array([2, 3]);
    const scale = new Float32Array([4, 5]);
    const varianceEpsilon = .001;

    const result = uploadBatchNormDownload(
        x, [2, 2], mean, [1, 2], variance, [1, 2], null, null, scale, [1, 2],
        varianceEpsilon);

    const expectedResult = new Float32Array([
      (x[0] - mean[0]) * scale[0] / Math.sqrt(variance[0] + varianceEpsilon),
      (x[1] - mean[1]) * scale[1] / Math.sqrt(variance[1] + varianceEpsilon),
      (x[2] - mean[0]) * scale[0] / Math.sqrt(variance[0] + varianceEpsilon),
      (x[3] - mean[1]) * scale[1] / Math.sqrt(variance[1] + varianceEpsilon)
    ]);
    test_util.expectArraysClose(result, expectedResult, 1e-5);
  }


() => {
    const x = new Float32Array([2, 100, 4, 400]);
    const mean = new Float32Array([1, 2]);
    const variance = new Float32Array([2, 3]);
    const offset = new Float32Array([4, 5]);
    const varianceEpsilon = .001;

    const result = uploadBatchNormDownload(
        x, [2, 2], mean, [1, 2], variance, [1, 2], offset, [1, 2], null, null,
        varianceEpsilon);

    const expectedResult = new Float32Array([
      offset[0] +
          (x[0] - mean[0]) * 1 / Math.sqrt(variance[0] + varianceEpsilon),
      offset[1] +
          (x[1] - mean[1]) * 1 / Math.sqrt(variance[1] + varianceEpsilon),
      offset[0] +
          (x[2] - mean[0]) * 1 / Math.sqrt(variance[0] + varianceEpsilon),
      offset[1] +
          (x[3] - mean[1]) * 1 / Math.sqrt(variance[1] + varianceEpsilon)
    ]);
    test_util.expectArraysClose(result, expectedResult, 1e-5);
  }


() => {
    const x = new Float32Array([2, 100, 4, 400]);
    const mean = new Float32Array([1, 2]);
    const variance = new Float32Array([2, 3]);
    const offset = new Float32Array([3, 4]);
    const scale = new Float32Array([4, 5]);
    const varianceEpsilon = .001;

    const result = uploadBatchNormDownload(
        x, [2, 2], mean, [1, 2], variance, [1, 2], offset, [1, 2], scale,
        [1, 2], varianceEpsilon);

    const expectedResult = new Float32Array([
      offset[0] +
          (x[0] - mean[0]) * scale[0] /
              Math.sqrt(variance[0] + varianceEpsilon),
      offset[1] +
          (x[1] - mean[1]) * scale[1] /
              Math.sqrt(variance[1] + varianceEpsilon),
      offset[0] +
          (x[2] - mean[0]) * scale[0] /
              Math.sqrt(variance[0] + varianceEpsilon),
      offset[1] +
          (x[3] - mean[1]) * scale[1] / Math.sqrt(variance[1] + varianceEpsilon)
    ]);
    test_util.expectArraysClose(result, expectedResult, 1e-5);
  }


() => {
    const x = new Float32Array([
      0.49955603, 0.04158615, -1.09440524, 2.03854165, -0.61578344, 2.87533573,
      1.18105987, 0.807462, 1.87888837, 2.26563962, -0.37040935, 1.35848753,
      -0.75347094, 0.15683117, 0.91925946, 0.34121279, 0.92717143, 1.89683965
    ]);
    const mean = new Float32Array([0.39745062, -0.48062894, 0.4847822]);
    const variance = new Float32Array([0.32375343, 0.67117643, 1.08334653]);
    const offset = new Float32Array([0.69398749, -1.29056387, 0.9429723]);
    const scale = new Float32Array([-0.5607271, 0.9878457, 0.25181573]);
    const varianceEpsilon = .001;

    const result = uploadBatchNormDownload(
        x, [2, 9], mean, [1, 3], variance, [1, 3], offset, [1, 3], scale,
        [1, 3], varianceEpsilon);

    const expectedResult = new Float32Array([
      0.59352049, -0.66135202, 0.5610874, -0.92077015, -1.45341019, 1.52106473,
      -0.07704776, 0.26144429, 1.28010017, -1.14422404, -1.15776136, 1.15425493,
      1.82644104, -0.52249442, 1.04803919, 0.74932291, 0.40568101, 1.2844412
    ]);
    test_util.expectArraysClose(result, expectedResult, 1e-5);
  }


export class CreateFunctionDefinitionCommand extends $Command<
  CreateFunctionDefinitionCommandInput,
  CreateFunctionDefinitionCommandOutput,
  GreengrassClientResolvedConfig
> {
  // Start section: command_properties
  // End section: command_properties

  constructor(readonly input: CreateFunctionDefinitionCommandInput) {
    // Start section: command_constructor
    super();
    // End section: command_constructor
  }

  resolveMiddleware(
    clientStack: MiddlewareStack<ServiceInputTypes, ServiceOutputTypes>,
    configuration: GreengrassClientResolvedConfig,
    options?: __HttpHandlerOptions
  ): Handler<CreateFunctionDefinitionCommandInput, CreateFunctionDefinitionCommandOutput> {
    this.middlewareStack.use(getSerdePlugin(configuration, this.serialize, this.deserialize));

    const stack = clientStack.concat(this.middlewareStack);

    const { logger } = configuration;
    const handlerExecutionContext: HandlerExecutionContext = {
      logger,
      inputFilterSensitiveLog: CreateFunctionDefinitionRequest.filterSensitiveLog,
      outputFilterSensitiveLog: CreateFunctionDefinitionResponse.filterSensitiveLog,
    };
    const { requestHandler } = configuration;
    return stack.resolve(
      (request: FinalizeHandlerArguments<any>) =>
        requestHandler.handle(request.request as __HttpRequest, options || {}),
      handlerExecutionContext
    );
  }

  private serialize(input: CreateFunctionDefinitionCommandInput, context: __SerdeContext): Promise<__HttpRequest> {
    return serializeAws_restJson1CreateFunctionDefinitionCommand(input, context);
  }

  private deserialize(output: __HttpResponse, context: __SerdeContext): Promise<CreateFunctionDefinitionCommandOutput> {
    return deserializeAws_restJson1CreateFunctionDefinitionCommand(output, context);
  }

  // Start section: command_body_extra
  // End section: command_body_extra
}


export type CreateFunctionDefinitionCommandInput = CreateFunctionDefinitionRequest;


export type CreateFunctionDefinitionCommandOutput = CreateFunctionDefinitionResponse & __MetadataBearer;


resolveMiddleware(
    clientStack: MiddlewareStack<ServiceInputTypes, ServiceOutputTypes>,
    configuration: GreengrassClientResolvedConfig,
    options?: __HttpHandlerOptions
  ): Handler<CreateFunctionDefinitionCommandInput, CreateFunctionDefinitionCommandOutput> {
    this.middlewareStack.use(getSerdePlugin(configuration, this.serialize, this.deserialize));

    const stack = clientStack.concat(this.middlewareStack);

    const { logger } = configuration;
    const handlerExecutionContext: HandlerExecutionContext = {
      logger,
      inputFilterSensitiveLog: CreateFunctionDefinitionRequest.filterSensitiveLog,
      outputFilterSensitiveLog: CreateFunctionDefinitionResponse.filterSensitiveLog,
    };
    const { requestHandler } = configuration;
    return stack.resolve(
      (request: FinalizeHandlerArguments<any>) =>
        requestHandler.handle(request.request as __HttpRequest, options || {}),
      handlerExecutionContext
    );
  }


private serialize(input: CreateFunctionDefinitionCommandInput, context: __SerdeContext): Promise<__HttpRequest> {
    return serializeAws_restJson1CreateFunctionDefinitionCommand(input, context);
  }


private deserialize(output: __HttpResponse, context: __SerdeContext): Promise<CreateFunctionDefinitionCommandOutput> {
    return deserializeAws_restJson1CreateFunctionDefinitionCommand(output, context);
  }


(validLogger: Logger, forTesting?: ForTesting): Logger => {
  let conditionalLogger = {};
  Object.entries(validLogger).forEach(([target, func]) => {
    // The logger should be validated long before this point
    // eslint-disable-next-line security/detect-object-injection
    conditionalLogger[target] = (message: any): void => {
      if (shouldLog(target as LoggerKey, forTesting)) {
        func(message);
      }
    };
  });
  return conditionalLogger as Logger;
}


([target, func]) => {
    // The logger should be validated long before this point
    // eslint-disable-next-line security/detect-object-injection
    conditionalLogger[target] = (message: any): void => {
      if (shouldLog(target as LoggerKey, forTesting)) {
        func(message);
      }
    };
  }


(message: any): void => {
      if (shouldLog(target as LoggerKey, forTesting)) {
        func(message);
      }
    }


() => {
    test('returns array of ICard', () => {
        const cards = generateCards();

        cards.forEach((card) => {
            expect(card).toEqual(
                expect.objectContaining({
                    id: expect.any(String),
                    rank: expect.any(Number),
                    isDown: expect.any(Boolean),
                    suit: expect.any(String),
                }),
            );
        });
    });
}


() => {
        const cards = generateCards();

        cards.forEach((card) => {
            expect(card).toEqual(
                expect.objectContaining({
                    id: expect.any(String),
                    rank: expect.any(Number),
                    isDown: expect.any(Boolean),
                    suit: expect.any(String),
                }),
            );
        });
    }


(card) => {
            expect(card).toEqual(
                expect.objectContaining({
                    id: expect.any(String),
                    rank: expect.any(Number),
                    isDown: expect.any(Boolean),
                    suit: expect.any(String),
                }),
            );
        }


declare function applyDefinitions(definitions: any, manipulatorStyle: any): boolean;


declare function applyPreset(name: any, manipulatorStyle: any): boolean;


declare function registerManipulatorType(type: any, classDef: any): void;


declare function registerStylePreset(name: any, definitions: any): void;


export interface T100 {
  applyDefinitions: typeof applyDefinitions;
  applyPreset: typeof applyPreset;
  registerManipulatorType: typeof registerManipulatorType;
  registerStylePreset: typeof registerStylePreset;
}


export function PluginDetailsBody({ plugin, queryParams, pageId }: Props): JSX.Element {
  const styles = useStyles2(getStyles);
  const { value: pluginConfig } = usePluginConfig(plugin);

  if (pageId === PluginTabIds.OVERVIEW) {
    return (
      <div
        className={cx(styles.readme, styles.container)}
        dangerouslySetInnerHTML={{
          __html: plugin.details?.readme ?? 'No plugin help or readme markdown file was found',
        }}
      />
    );
  }


(theme: GrafanaTheme2) => ({
  container: css`
    padding: ${theme.spacing(3, 4)};
  `,
  readme: css`
    & img {
      max-width: 100%;
    }

    h1,
    h2,
    h3 {
      margin-top: ${theme.spacing(3)};
      margin-bottom: ${theme.spacing(2)};
    }

    *:first-child {
      margin-top: 0;
    }

    li {
      margin-left: ${theme.spacing(2)};
      & > p {
        margin: ${theme.spacing()} 0;
      }
    }
  `,
})


type Props = {
  plugin: CatalogPlugin;
  queryParams: UrlQueryMap;
  pageId: string;
};


() => {
  const readTestFiles = (): {
    body: string;
    name: string;
    shouldBeAccepted: boolean;
  }[] => {
    const testDir = path.resolve(__dirname, "./data/parsing");
    return fs
      .readdirSync(testDir)
      .filter(
        (fileName: string) =>
          fileName.startsWith("y_") || fileName.startsWith("n_")
      )
      .map((fileName: string) => {
        const filePath = path.resolve(testDir, fileName);
        const body = fs.readFileSync(filePath, "utf8");
        const match = /[y|n|i]_(.*)\.json/.exec(fileName);
        const name = match[1];
        const shouldBeAccepted = fileName.startsWith("y_");

        return {
          body,
          name,
          shouldBeAccepted,
        };
      });
  };

  const testDataFiles = readTestFiles();

  const testCases = TEST_CASES_OPTIONS_MATRIX.flatMap((options) => {
    return testDataFiles.map((dataFile) => ({
      name: dataFile.name,
      optionsProfile: options.name,
      options: options.options,
      body: dataFile.body,
      shouldBeAccepted: dataFile.shouldBeAccepted,
    }));
  });

  test.each(testCases.filter((test) => test.shouldBeAccepted))(
    "test $name should be parsed correctly [$optionsProfile]",
    async ({ body, options }) => {
      const parsed = await parse(body, options);

      expect(parsed).toEqual(JSON.parse(body));
    }
  );

  test.each(testCases.filter((test) => !test.shouldBeAccepted))(
    "test $name should throw error [$optionsProfile]",
    async ({ body, options }) => {
      await expect(parse(body, options)).rejects.toThrow();
    }
  );
}


(): {
    body: string;
    name: string;
    shouldBeAccepted: boolean;
  }[] => {
    const testDir = path.resolve(__dirname, "./data/parsing");
    return fs
      .readdirSync(testDir)
      .filter(
        (fileName: string) =>
          fileName.startsWith("y_") || fileName.startsWith("n_")
      )
      .map((fileName: string) => {
        const filePath = path.resolve(testDir, fileName);
        const body = fs.readFileSync(filePath, "utf8");
        const match = /[y|n|i]_(.*)\.json/.exec(fileName);
        const name = match[1];
        const shouldBeAccepted = fileName.startsWith("y_");

        return {
          body,
          name,
          shouldBeAccepted,
        };
      });
  }


(fileName: string) =>
          fileName.startsWith("y_") || fileName.startsWith("n_")


(fileName: string) => {
        const filePath = path.resolve(testDir, fileName);
        const body = fs.readFileSync(filePath, "utf8");
        const match = /[y|n|i]_(.*)\.json/.exec(fileName);
        const name = match[1];
        const shouldBeAccepted = fileName.startsWith("y_");

        return {
          body,
          name,
          shouldBeAccepted,
        };
      }


(options) => {
    return testDataFiles.map((dataFile) => ({
      name: dataFile.name,
      optionsProfile: options.name,
      options: options.options,
      body: dataFile.body,
      shouldBeAccepted: dataFile.shouldBeAccepted,
    }));
  }


(dataFile) => ({
      name: dataFile.name,
      optionsProfile: options.name,
      options: options.options,
      body: dataFile.body,
      shouldBeAccepted: dataFile.shouldBeAccepted,
    })


(test) => test.shouldBeAccepted


async ({ body, options }) => {
      const parsed = await parse(body, options);

      expect(parsed).toEqual(JSON.parse(body));
    }


(test) => !test.shouldBeAccepted


async ({ body, options }) => {
      await expect(parse(body, options)).rejects.toThrow();
    }


function stringifyArray(arry: lp.Node[], options: { lineBreak: string }): string {
    const len = arry.length
    let ret = ''
    for (let i = 0; i < len; i++) {
        const cur = arry[i]
        ret += stringify(cur, options)
        if (lp.isCommandParameter(cur) || lp.isSubscript(cur) || lp.isSuperscript(cur)) {
            continue
        }
        if (i + 1 < len && lp.isTextString(arry[i + 1])) {
            ret += ' '
            continue
        }
        if (i + 1 < len && lp.isMathCharacter(arry[i + 1]) && !lp.isMathCharacter(cur)) {
            ret += ' '
            continue
        }
        if (i + 1 < len && lp.isCommand(cur) && cur.args.length === 0 && lp.isCommandParameter(arry[i + 1])) {
            ret += ' '
            continue
        }
    }
    return ret
}


export function stringify(
    node: lp.Node | lp.Node[],
    options = { lineBreak: '' }
): string {
    const lineBreak = options.lineBreak
    if (Array.isArray(node)) {
        return stringifyArray(node, options)
    }
    if (lp.isTextString(node)) {
        return node.content
    }
    if (lp.isCommand(node)) {
        return '\\' + node.name + stringifyArray(node.args, options)
    }
    if (lp.isAmsMathTextCommand(node)) {
        return '\\text{' + node.arg + '}'
    }
    if (lp.isDefCommand(node)) {
        return '\\def' + node.token + stringifyArray(node.args, options)
    }
    if (lp.isEnvironment(node) || lp.isMathEnv(node) || lp.isMathEnvAligned(node)) {
        const begin = '\\begin{' + node.name + '}'
        const args = stringifyArray(node.args, options)
        const content = stringifyArray(node.content, options)
        const end = '\\end{' + node.name + '}'
        return begin + args.trim() + lineBreak + content.trim() + lineBreak + end + lineBreak
    }
    if (lp.isGroup(node)) {
        return '{' + stringifyArray(node.content, options) + '}'
    }
    if (lp.isOptionalArg(node)) {
        return '[' + stringifyArray(node.content, options) + ']'
    }
    if (lp.isParbreak(node)) {
        return '\\par' + lineBreak
    }
    if (lp.isSuperscript(node)) {
        return '^' + stringifyArray(node.content, options)
    }
    if (lp.isSubscript(node)) {
        return '_' + stringifyArray(node.content, options)
    }
    if (lp.isAlignmentTab(node)) {
        return '&'
    }
    if (lp.isCommandParameter(node)) {
        return '#' + node.nargs
    }
    if (lp.isActiveCharacter(node)) {
        return '~'
    }
    if (lp.isIgnore(node)) {
        return ''
    }
    if (lp.isVerb(node)) {
        return '\\verb' + node.escape + node.content + node.escape
    }
    if (lp.isVerbatim(node)) {
        return '\\begin{verbatim}' + node.content + '\\end{verbatim}' + lineBreak
    }
    if (lp.isMinted(node)) {
        const args = stringify(node.args)
        return '\\begin{minted}' + args + node.content + '\\end{minted}' + lineBreak
    }
    if (lp.isLstlisting(node)) {
        const arg = node.arg ? stringify(node.arg) : ''
        return '\\begin{lstlisting}' + arg + node.content + '\\end{lstlisting}'
    }
    if (lp.isInlienMath(node)) {
        return '$' + stringifyArray(node.content, options) + '$'
    }
    if (lp.isDisplayMath(node)) {
        return '\\[' + lineBreak + stringifyArray(node.content, options).trim() + lineBreak + '\\]' + lineBreak
    }
    if (lp.isMathCharacter(node)) {
        return node.content
    }
    if (lp.isMatchingDelimiters(node)) {
        return '\\left' + node.left + stringifyArray(node.content, options) + '\\right' + node.right
    }
    if (lp.isMathDelimiters(node)) {
        return node.lcommand + node.left + stringifyArray(node.content, options) + node.rcommand + node.right
    }

    // node must be the never type here.
    const dummy: never = node
    return dummy
}


() => String


() => Date


@ObjectType()
export class DonationMinAggregate {

    @Field(() => Int, {nullable:true})
    id?: number;

    @Field(() => Int, {nullable:true})
    count?: number;

    @Field(() => String, {nullable:true})
    displayName?: string;

    @Field(() => String, {nullable:true})
    email?: string;

    @Field(() => String, {nullable:true})
    mobile?: string;

    @Field(() => String, {nullable:true})
    team?: string;

    @Field(() => String, {nullable:true})
    message?: string;

    @Field(() => Date, {nullable:true})
    createdAt?: Date | string;
}


(source: Source): void => {
    const widgetId: string = this.props.element.get("id")
    this.props.widgetMgr.setBoolValue(widgetId, this.state.value, source)
  }


(e: React.ChangeEvent<HTMLInputElement>): void => {
    const value = e.target.checked
    this.setState({ value }, () => this.setWidgetValue({ fromUi: true }))
  }


() => this.setWidgetValue({ fromUi: true })


(): React.ReactNode => {
    const label = this.props.element.get("label")
    const style = { width: this.props.width }

    return (
      <div className="Widget row-widget stCheckbox" style={style}>
        <UICheckbox
          checked={this.state.value}
          disabled={this.props.disabled}
          onChange={this.onChange}
          overrides={checkboxOverrides}
        >
          {label}
        </UICheckbox>
      </div>
    )
  }


class Checkbox extends React.PureComponent<Props, State> {
  public state: State = {
    value: this.props.element.get("default"),
  }

  public componentDidMount(): void {
    this.setWidgetValue({ fromUi: false })
  }

  private setWidgetValue = (source: Source): void => {
    const widgetId: string = this.props.element.get("id")
    this.props.widgetMgr.setBoolValue(widgetId, this.state.value, source)
  }

  private onChange = (e: React.ChangeEvent<HTMLInputElement>): void => {
    const value = e.target.checked
    this.setState({ value }, () => this.setWidgetValue({ fromUi: true }))
  }

  public render = (): React.ReactNode => {
    const label = this.props.element.get("label")
    const style = { width: this.props.width }

    return (
      <div className="Widget row-widget stCheckbox" style={style}>
        <UICheckbox
          checked={this.state.value}
          disabled={this.props.disabled}
          onChange={this.onChange}
          overrides={checkboxOverrides}
        >
          {label}
        </UICheckbox>
      </div>
    )
  }
}


interface Props {
  disabled: boolean
  element: ImmutableMap<string, any>
  widgetMgr: WidgetStateManager
  width: number
}


interface State {
  /**
   * The value specified by the user via the UI. If the user didn't touch this
   * widget's UI, the default value is used.
   */
  value: boolean
}


public componentDidMount(): void {
    this.setWidgetValue({ fromUi: false })
  }


() => {
  return {
    useField() {
      return {
        fieldName: 'email',
        defaultValue: '',
        error: '',
        registerField: jest.fn(),
      };
    },
  };
}