Skip to content

Commit

Permalink
Ensure inline precompile and colocated templates run template AS… (#309)
Browse files Browse the repository at this point in the history
Ensure inline precompile and colocated templates run template AST plugins.
  • Loading branch information
rwjblue authored Sep 30, 2019
2 parents 7b88419 + 2998af6 commit 2a3eed2
Show file tree
Hide file tree
Showing 18 changed files with 430 additions and 109 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ module.exports = {
'blueprints/*/index.js',
'config/**/*.js',
'tests/dummy/config/**/*.js',
'tests/dummy/lib/**/*.js',
],
excludedFiles: ['addon/**', 'addon-test-support/**', 'app/**', 'tests/dummy/app/**'],
parserOptions: {
Expand Down
10 changes: 10 additions & 0 deletions config/ember-try.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,16 @@ module.exports = function() {
devDependencies: {},
},
},
{
name: 'ember-octane',
ENV: {
// need to add a convienient API for this to @ember/edition-utils
EMBER_EDITION: 'octane',
},
npm: {
devDependencies: {},
},
},
{
name: 'with-ember-cli-htmlbars-inline-precompile',
npm: {
Expand Down
32 changes: 32 additions & 0 deletions ember-cli-build.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,43 @@
'use strict';

const EmberAddon = require('ember-cli/lib/broccoli/ember-addon');
const MergeTree = require('broccoli-merge-trees');
const { has } = require('@ember/edition-utils');

module.exports = function(defaults) {
let hasOctane = has('octane');
let appTree = 'tests/dummy/app';
if (hasOctane) {
appTree = new MergeTree(['tests/dummy/app', 'tests/colocation/app']);
}

let app = new EmberAddon(defaults, {
// Add options here
throwUnlessParallelizable: true,

trees: {
app: appTree,
},

babel: {
plugins: [
[
require.resolve('babel-plugin-debug-macros'),
{
flags: [
{
name: '@ember/edition-fake-module',
source: '@ember/edition-fake-module',
flags: {
HAS_OCTANE: hasOctane,
},
},
],
},
'debug macros - octane flag',
],
],
},
});

/*
Expand Down
20 changes: 18 additions & 2 deletions lib/colocated-broccoli-plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const copyFileSync = require('fs-copy-file-sync');
const path = require('path');
const walkSync = require('walk-sync');
const Plugin = require('broccoli-plugin');
const logger = require('heimdalljs-logger')('ember-cli-htmlbars:colocated-broccoli-plugin');

function detectRootName(files) {
let [first] = files;
Expand Down Expand Up @@ -79,8 +80,19 @@ module.exports = class ColocatedTemplateProcessor extends Plugin {
let templateContents = fs.readFileSync(inputPath, { encoding: 'utf8' });
let jsContents = null;

// TODO: deal with hygiene?
let prefix = `import { hbs } from 'ember-cli-htmlbars';\nconst __COLOCATED_TEMPLATE__ = hbs\`${templateContents}\`;\n`;
let hbsInvocationOptions = {
contents: templateContents,
moduleName: filePath,
parseOptions: {
srcName: filePath,
},
};
let hbsInvocation = `hbs(${JSON.stringify(templateContents)}, ${JSON.stringify(
hbsInvocationOptions
)})`;
let prefix = `import { hbs } from 'ember-cli-htmlbars';\nconst __COLOCATED_TEMPLATE__ = ${hbsInvocation};\n`;

logger.debug(`processing colocated template: ${filePath} (template-only: ${hasJSFile})`);

if (hasJSFile) {
// add the template, call setComponentTemplate
Expand Down Expand Up @@ -118,9 +130,13 @@ module.exports = class ColocatedTemplateProcessor extends Plugin {
return;
}

logger.debug(`copying unchanged file: ${filePath}`);

// TODO: don't speculatively mkdirSync (likely do in a try/catch with ENOENT)
mkdirp.sync(path.dirname(outputPath));
copyFileSync(inputPath, outputPath);
});

logger.info(`copied over (unchanged): ${filesToCopy.length} files`);
}
};
19 changes: 7 additions & 12 deletions lib/ember-addon-main.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ module.exports = {
this._cachedShouldColocateTemplates =
hasOctane && hasValidBabelVersion && hasValidEmberCLIVersion;

logger.info(
`Colocation processing: ${this._cachedShouldColocateTemplates} (hasOctane: ${hasOctane}; hasValidEmberCLIVersion: ${hasValidEmberCLIVersion}; hasVali
dBabelVersion: ${hasValidBabelVersion};`
);

return this._cachedShouldColocateTemplates;
},

Expand Down Expand Up @@ -94,9 +99,8 @@ module.exports = {
// add the babel-plugin-htmlbars-inline-precompile to the list of plugins
// used by `ember-cli-babel` addon
if (!this._isInlinePrecompileBabelPluginRegistered(babelPlugins)) {
let pluginWrappers = this.astPlugins();
let pluginInfo = this.astPlugins();
let templateCompilerPath = this.templateCompilerPath();
let pluginInfo = utils.setupPlugins(pluginWrappers);

let modules = {
'ember-cli-htmlbars': 'hbs',
Expand Down Expand Up @@ -137,16 +141,7 @@ module.exports = {
});
} else {
logger.debug('NOT using parallel API with for babel inline precompilation plugin');

let blockingPlugins = pluginWrappers
.map(wrapper => {
if (wrapper.parallelBabel === undefined) {
return wrapper.name;
}
})
.filter(Boolean);

logger.debug('Prevented by these plugins: ' + blockingPlugins);
logger.debug('Prevented by these plugins: ' + pluginInfo.unparallelizableWrappers);

let htmlBarsPlugin = utils.setup(pluginInfo, {
projectConfig: this.projectConfig(),
Expand Down
8 changes: 6 additions & 2 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ function template(templateCompiler, string, options) {
}

function setup(pluginInfo, options) {
// borrowed from ember-cli-htmlbars http://git.io/vJDrW
let projectConfig = options.projectConfig || {};
let templateCompilerPath = options.templateCompilerPath;

Expand All @@ -129,7 +128,9 @@ function setup(pluginInfo, options) {

let cacheKey = makeCacheKey(templateCompilerPath, pluginInfo);

registerPlugins(templateCompiler, pluginInfo.plugins);
registerPlugins(templateCompiler, {
ast: pluginInfo.plugins,
});

let { precompile } = templateCompiler;
precompile.baseDir = () => path.resolve(__dirname, '..');
Expand All @@ -156,6 +157,7 @@ function setupPlugins(wrappers) {
let plugins = [];
let cacheKeys = [];
let parallelConfigs = [];
let unparallelizableWrappers = [];
let dependencyInvalidation = false;
let canParallelize = true;

Expand All @@ -170,6 +172,7 @@ function setupPlugins(wrappers) {
if (wrapper.parallelBabel) {
parallelConfigs.push(wrapper.parallelBabel);
} else {
unparallelizableWrappers.push(wrapper.name);
canParallelize = false;
}

Expand Down Expand Up @@ -203,6 +206,7 @@ function setupPlugins(wrappers) {
cacheKeys,
parallelConfigs,
canParallelize,
unparallelizableWrappers,
hasDependencyInvalidation: !!dependencyInvalidation,
};
}
Expand Down
8 changes: 4 additions & 4 deletions node-tests/colocated-plugin-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ describe('ColocatedTemplateCompiler', function() {
'foo.js':
stripIndent`
import { hbs } from 'ember-cli-htmlbars';
const __COLOCATED_TEMPLATE__ = hbs\`{{yield}}\`;
const __COLOCATED_TEMPLATE__ = hbs("{{yield}}", {"contents":"{{yield}}","moduleName":"app-name-here/components/foo.hbs","parseOptions":{"srcName":"app-name-here/components/foo.hbs"}});
import templateOnly from '@ember/component/template-only';
export default templateOnly();` + '\n',
Expand Down Expand Up @@ -92,7 +92,7 @@ describe('ColocatedTemplateCompiler', function() {
components: {
'foo.js': stripIndent`
import { hbs } from 'ember-cli-htmlbars';
const __COLOCATED_TEMPLATE__ = hbs\`{{yield}}\`;
const __COLOCATED_TEMPLATE__ = hbs("{{yield}}", {"contents":"{{yield}}","moduleName":"app-name-here/components/foo.hbs","parseOptions":{"srcName":"app-name-here/components/foo.hbs"}});
import Component from '@glimmer/component';
export default class FooComponent extends Component {}
Expand Down Expand Up @@ -135,7 +135,7 @@ describe('ColocatedTemplateCompiler', function() {
'foo.js':
stripIndent`
import { hbs } from 'ember-cli-htmlbars';
const __COLOCATED_TEMPLATE__ = hbs\`{{yield}}\`;
const __COLOCATED_TEMPLATE__ = hbs("{{yield}}", {"contents":"{{yield}}","moduleName":"@scope-name/addon-name-here/components/foo.hbs","parseOptions":{"srcName":"@scope-name/addon-name-here/components/foo.hbs"}});
import templateOnly from '@ember/component/template-only';
export default templateOnly();` + '\n',
Expand Down Expand Up @@ -182,7 +182,7 @@ describe('ColocatedTemplateCompiler', function() {
components: {
'foo.js': stripIndent`
import { hbs } from 'ember-cli-htmlbars';
const __COLOCATED_TEMPLATE__ = hbs\`{{yield}}\`;
const __COLOCATED_TEMPLATE__ = hbs("{{yield}}", {"contents":"{{yield}}","moduleName":"@scope-name/addon-name-here/components/foo.hbs","parseOptions":{"srcName":"@scope-name/addon-name-here/components/foo.hbs"}});
import Component from '@glimmer/component';
export default class FooComponent extends Component {}
Expand Down
5 changes: 5 additions & 0 deletions node-tests/utils_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ describe('utils', function() {
cacheKeys: [],
parallelConfigs: [],
canParallelize: true,
unparallelizableWrappers: [],
hasDependencyInvalidation: false,
});
});
Expand Down Expand Up @@ -74,20 +75,23 @@ describe('utils', function() {
cacheKeys: ['something', 'something else'],
parallelConfigs: ['something', 'something else'],
canParallelize: true,
unparallelizableWrappers: [],
hasDependencyInvalidation: false,
});
});

it('canParallelize is false for 1+ plugins without "parallelBabel" property', function() {
let pluginWrappers = [
{
name: 'first',
plugin() {},
cacheKey() {
return this.parallelBabel;
},
parallelBabel: 'something',
},
{
name: 'second',
plugin() {},
cacheKey() {
return 'something else';
Expand All @@ -102,6 +106,7 @@ describe('utils', function() {
cacheKeys: ['something', 'something else'],
parallelConfigs: ['something'],
canParallelize: false,
unparallelizableWrappers: ['second'],
hasDependencyInvalidation: false,
});
});
Expand Down
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,18 @@
},
"devDependencies": {
"@ember/optional-features": "^1.0.0",
"babel-plugin-debug-macros": "^0.3.3",
"broccoli-merge-trees": "^3.0.2",
"broccoli-test-helper": "^2.0.0",
"chai": "^4.2.0",
"co": "^4.6.0",
"ember-cli": "~3.12.0",
"ember-cli": "~3.13.0",
"ember-cli-app-version": "^3.2.0",
"ember-cli-babel": "^7.11.1",
"ember-cli-dependency-checker": "^3.2.0",
"ember-cli-inject-live-reload": "^2.0.1",
"ember-cli-template-lint": "^1.0.0-beta.3",
"ember-cli-version-checker": "^3.1.3",
"ember-export-application-global": "^2.0.0",
"ember-load-initializers": "^2.1.0",
"ember-maybe-import-regenerator": "^0.1.6",
Expand All @@ -75,6 +78,7 @@
"fixturify": "^1.2.0",
"loader.js": "^4.7.0",
"mocha": "^6.2.0",
"module-name-inliner": "link:./tests/dummy/lib/module-name-inliner",
"prettier": "^1.18.2",
"qunit-dom": "^0.9.0",
"release-it": "^12.2.1",
Expand Down
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions tests/colocation/app/components/foo.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Module: {{module-name-inliner}}
1 change: 0 additions & 1 deletion tests/dummy/app/components/foo.hbs

This file was deleted.

4 changes: 3 additions & 1 deletion tests/dummy/config/optional-features.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
{
"jquery-integration": false
"application-template-wrapper": false,
"jquery-integration": false,
"template-only-glimmer-components": true
}
49 changes: 49 additions & 0 deletions tests/dummy/lib/module-name-inliner/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
'use strict';

let VersionChecker = require('ember-cli-version-checker');

module.exports = {
name: require('./package').name,

isDevelopingAddon() {
return true;
},

setupPreprocessorRegistry(type, registry) {
// can only add the plugin with this style on newer Ember versions
let checker = new VersionChecker(this.project);
if (checker.forEmber().gte('3.1.0')) {
registry.add('htmlbars-ast-plugin', this.buildPlugin());
}
},

buildPlugin() {
// https://astexplorer.net/#/gist/7c8399056873e1ddbd2b1acf0a41592a/e08f2f850de449b77b8ad995085496a1100dfd1f
return {
name: 'module-name-inliner',
baseDir() {
return __dirname;
},
parallelBabel: {
requireFile: __filename,
buildUsing: 'buildPlugin',
params: {},
},
plugin(env) {
let { builders } = env.syntax;

return {
name: 'module-name-inliner',

visitor: {
PathExpression(node) {
if (node.original === 'module-name-inliner') {
return builders.string(env.moduleName);
}
},
},
};
},
};
},
};
10 changes: 10 additions & 0 deletions tests/dummy/lib/module-name-inliner/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "module-name-inliner",
"version": "0.1.0",
"keywords": [
"ember-addon"
],
"dependencies": {
"ember-cli-version-checker": "*"
}
}
20 changes: 20 additions & 0 deletions tests/integration/components/colocation-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
import { HAS_OCTANE } from '@ember/edition-fake-module';

module('tests/integration/components/test-inline-precompile', function(hooks) {
if (!HAS_OCTANE) {
// can only run against 3.13+ (due to colocation support)
return;
}

setupRenderingTest(hooks);

test('registered ast plugins run against colocated templates (template-only)', async function(assert) {
await render(hbs`<Foo />`);

assert.equal(this.element.textContent.trim(), 'Module: dummy/components/foo.hbs');
});
});
Loading

0 comments on commit 2a3eed2

Please sign in to comment.