Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reform internal use of template compiler #20587

Merged
merged 1 commit into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ jobs:
- name: build stable type definitions
run: pnpm build:types
- name: install TS@${{matrix.ts-version}}
run: pnpm add --save-dev typescript@${{ matrix.ts-version }}
run: pnpm add --save-dev --workspace-root typescript@${{ matrix.ts-version }}
- name: Check published and internal types with TS@${{matrix.ts-version}}
run: pnpm type-check

Expand Down
39 changes: 2 additions & 37 deletions broccoli/glimmer-template-compiler.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,4 @@
'use strict';

const Filter = require('broccoli-persistent-filter');
const { stripIndent } = require('common-tags');

GlimmerTemplatePrecompiler.prototype = Object.create(Filter.prototype);

function GlimmerTemplatePrecompiler(inputTree, options) {
if (!(this instanceof GlimmerTemplatePrecompiler)) {
return new GlimmerTemplatePrecompiler(inputTree, options);
}

Filter.call(this, inputTree, {});

this.inputTree = inputTree;
if (!options.glimmer) {
throw new Error('No glimmer option provided!');
}
this.precompile = options.glimmer.precompile;
}

GlimmerTemplatePrecompiler.prototype.extensions = ['hbs'];
GlimmerTemplatePrecompiler.prototype.targetExtension = 'js';

GlimmerTemplatePrecompiler.prototype.baseDir = function () {
return __dirname;
};

GlimmerTemplatePrecompiler.prototype.processString = function (content, relativePath) {
let compiled = this.precompile(content, {
meta: { moduleName: relativePath },
});
return stripIndent`
import { templateFactory } from '@glimmer/opcode-compiler';
export default templateFactory(${compiled});
`;
};

module.exports = GlimmerTemplatePrecompiler;
require('@swc-node/register');
module.exports = require('../packages/ember-template-compiler/minimal.ts');
18 changes: 3 additions & 15 deletions broccoli/packages.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ const { VERSION } = require('./version');
const PackageJSONWriter = require('./package-json-writer');
const WriteFile = require('broccoli-file-creator');
const StringReplace = require('broccoli-string-replace');
const GlimmerTemplatePrecompiler = require('./glimmer-template-compiler');
const VERSION_PLACEHOLDER = /VERSION_STRING_PLACEHOLDER/g;
const canaryFeatures = require('./canary-features');

Expand Down Expand Up @@ -54,32 +53,21 @@ module.exports.qunit = function _qunit() {

module.exports.getPackagesES = function getPackagesES() {
let input = new Funnel(`packages`, {
exclude: ['loader/**', 'external-helpers/**'],
exclude: ['loader/**', 'external-helpers/**', '**/node_modules'],
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR makes all the packages real pnpm workspaces, which was necessary to make the ember-template-compiler package actually evaluatable in node. Previously not all packages were. This extra filtering is necessary now that pnpm is creating node_modules directories inside the packages.

destDir: `packages`,
});

let debuggedInput = debugTree(input, `get-packages-es:input`);

let compiledTemplatesAndTypescript = new GlimmerTemplatePrecompiler(debuggedInput, {
persist: true,
glimmer: require('@glimmer/compiler'),
annotation: `get-packages-es templates -> es`,
});

let debuggedCompiledTemplatesAndTypeScript = debugTree(
compiledTemplatesAndTypescript,
`get-packages-es:templates-output`
);

let nonTypeScriptContents = debugTree(
new Funnel(debuggedCompiledTemplatesAndTypeScript, {
new Funnel(debuggedInput, {
srcDir: 'packages',
exclude: ['**/*.ts'],
}),
'get-packages-es:js:output'
);

let typescriptContents = new Funnel(debuggedCompiledTemplatesAndTypeScript, {
let typescriptContents = new Funnel(debuggedInput, {
include: ['**/*.ts'],
});

Expand Down
21 changes: 13 additions & 8 deletions ember-cli-build.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,21 @@ module.exports = function ({ project }) {
let emberBundles = withTargets(project, emberSource.buildEmberBundles.bind(emberSource));

let packages = debugTree(
new MergeTrees([
// dynamically generated packages
emberVersionES(),
new MergeTrees(
[
// packages/** (after typescript compilation)
getPackagesES(),

// packages/** (after typescript compilation)
getPackagesES(),
emberVersionES(),

// externalized helpers
babelHelpers(),
]),
// externalized helpers
babelHelpers(),
],
{
// we're replacing the ember/verion file with the actual version number
overwrite: true,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The template compiler imports the version. Previously that would die because the version file is dynamically created. Now we have a placeholder file on disk that gets replaced in the build, so that our internal usage of template compiler doesn't die.

}
),
'packages:initial'
);

Expand Down
12 changes: 12 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,17 @@ module.exports = {
let isEmberSource = this.project.name() === 'ember-source';
let babelHelperPlugin = injectBabelHelpers(isEmberSource);

let compilerPath;
if (isEmberSource) {
// Here we are using the template compiler by directly evaluating it in
// node, because we *are* the build that produces
// ember-template-compiler.js.
compilerPath = path.resolve(__dirname, '../broccoli/glimmer-template-compiler');
} else {
// When we're building an app, we use the already built template compiler.
compilerPath = path.resolve(__dirname, '../dist/ember-template-compiler.js');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This keeps the exact old behavior when building apps, and only changes the behavior when ember is building itself.

}

let options = {
'ember-cli-babel': {
disableDebugTooling: true,
Expand All @@ -155,6 +166,7 @@ module.exports = {
plugins: [
babelHelperPlugin,
buildDebugMacroPlugin(!isProduction),
['babel-plugin-ember-template-compilation', { compilerPath }],
...vmBabelPlugins({ isDebug: !isProduction }),
],
}),
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@
"@embroider/shared-internals": "^2.5.0",
"@rollup/plugin-babel": "^6.0.3",
"@simple-dom/document": "^1.4.0",
"@swc/core": "^1.3.100",
"@swc-node/register": "^1.6.8",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is how we can directly evaluate the template compiler without a build.

"@tsconfig/ember": "^2.0.0",
"@types/node": "^18.11.11",
"@types/qunit": "^2.19.4",
Expand Down
3 changes: 0 additions & 3 deletions packages/@ember/-internals/glimmer/lib/templates/empty.d.ts

This file was deleted.

Empty file.
4 changes: 4 additions & 0 deletions packages/@ember/-internals/glimmer/lib/templates/empty.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { precompileTemplate } from '@ember/template-compilation';
export default precompileTemplate('', {
moduleName: 'packages/@ember/-internals/glimmer/lib/templates/empty.hbs',
});
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was able to drop all special support for hbs files, and several hacks around their types, by making them just be the equivalent javascript.

3 changes: 0 additions & 3 deletions packages/@ember/-internals/glimmer/lib/templates/input.d.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<input
import { precompileTemplate } from '@ember/template-compilation';
export default precompileTemplate(
`<input
{{!-- for compatibility --}}
id={{this.id}}
class={{this.class}}
Expand All @@ -14,4 +16,6 @@
{{on "keyup" this.keyUp}}
{{on "paste" this.valueDidChange}}
{{on "cut" this.valueDidChange}}
/>
/>`,
{ moduleName: 'packages/@ember/-internals/glimmer/lib/templates/input.hbs' }
);
3 changes: 0 additions & 3 deletions packages/@ember/-internals/glimmer/lib/templates/link-to.d.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<a
import { precompileTemplate } from '@ember/template-compilation';
export default precompileTemplate(
`<a
{{!-- for compatibility --}}
id={{this.id}}
class={{this.class}}
Expand All @@ -15,4 +17,6 @@
href={{this.href}}

{{on 'click' this.click}}
>{{yield}}</a>
>{{yield}}</a>`,
{ moduleName: 'packages/@ember/-internals/glimmer/lib/templates/link-to.hbs' }
);
3 changes: 0 additions & 3 deletions packages/@ember/-internals/glimmer/lib/templates/outlet.d.ts

This file was deleted.

This file was deleted.

4 changes: 4 additions & 0 deletions packages/@ember/-internals/glimmer/lib/templates/outlet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { precompileTemplate } from '@ember/template-compilation';
export default precompileTemplate(`{{component (-outlet)}}`, {
moduleName: 'packages/@ember/-internals/glimmer/lib/templates/outlet.hbs',
});
3 changes: 0 additions & 3 deletions packages/@ember/-internals/glimmer/lib/templates/root.d.ts

This file was deleted.

1 change: 0 additions & 1 deletion packages/@ember/-internals/glimmer/lib/templates/root.hbs

This file was deleted.

4 changes: 4 additions & 0 deletions packages/@ember/-internals/glimmer/lib/templates/root.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { precompileTemplate } from '@ember/template-compilation';
export default precompileTemplate(`{{component this}}`, {
moduleName: 'packages/@ember/-internals/glimmer/lib/templates/root.hbs',
});

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<textarea
import { precompileTemplate } from '@ember/template-compilation';
export default precompileTemplate(
`<textarea
{{!-- for compatibility --}}
id={{this.id}}
class={{this.class}}
Expand All @@ -12,4 +14,6 @@
{{on "keyup" this.keyUp}}
{{on "paste" this.valueDidChange}}
{{on "cut" this.valueDidChange}}
/>
/>`,
{ moduleName: 'packages/@ember/-internals/glimmer/lib/templates/textarea.hbs' }
);
5 changes: 4 additions & 1 deletion packages/@ember/debug/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import type { WarnFunc } from './lib/warn';
import _warn from './lib/warn';

export { registerHandler as registerWarnHandler } from './lib/warn';
export { registerHandler as registerDeprecationHandler, DeprecationOptions } from './lib/deprecate';
export {
registerHandler as registerDeprecationHandler,
type DeprecationOptions,
} from './lib/deprecate';
export { default as inspect } from './lib/inspect';
export { isTesting, setTesting } from './lib/testing';
export { default as captureRenderTree } from './lib/capture-render-tree';
Expand Down
12 changes: 12 additions & 0 deletions packages/ember-template-compiler/minimal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// The main entrypoint of ember-template-compiler is the fairly-crufty
// backward-compatible API. In contrast, this is the subset of that that's
// actually used by babel-plugin-ember-template-compilation.
//
// This module exists so that ember-source can build itself -- the
// ember-template-compiler.js bundle it an output of the build, but the build
// needs to compile templates. Unlike the full ./index.ts, this module can be
// directly evaluted in node because it doesn't try to pull in the whole kitchen
// sink.
export { default as precompile } from './lib/system/precompile';
export { buildCompileOptions as _buildCompileOptions } from './lib/system/compile-options';
export { preprocess as _preprocess, print as _print } from '@glimmer/syntax';
4 changes: 3 additions & 1 deletion packages/ember-template-compiler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"private": true,
"type": "module",
"exports": {
".": "./index.ts"
".": "./index.ts",
"./minimal": "./minimal.ts"
},
"dependencies": {
"@ember/-internals": "workspace:*",
Expand All @@ -21,6 +22,7 @@
"@ember/routing": "workspace:*",
"@ember/runloop": "workspace:*",
"@ember/service": "workspace:*",
"@ember/template-compilation": "workspace:*",
"@ember/utils": "workspace:*",
"@glimmer/compiler": "0.85.13",
"@glimmer/env": "^0.1.7",
Expand Down
2 changes: 0 additions & 2 deletions packages/ember/version.d.ts

This file was deleted.

2 changes: 2 additions & 0 deletions packages/ember/version.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// this file gets replaced with the real value during the build
export default 'VERSION_GOES_HERE' as string;
Loading
Loading