Skip to content

Commit

Permalink
Merge pull request #19704 from nlfurniss/remove-template-compiler.reg…
Browse files Browse the repository at this point in the history
…isterPlugin

[CLEANUP beta] Remove template-compiler.registerPlugin
  • Loading branch information
mixonic committed Aug 22, 2021
2 parents 955a5e6 + 6f39bcb commit bbb62dd
Show file tree
Hide file tree
Showing 6 changed files with 10 additions and 315 deletions.
2 changes: 0 additions & 2 deletions packages/ember-template-compiler/index.ts
Expand Up @@ -31,8 +31,6 @@ export {
default as compileOptions,
buildCompileOptions as _buildCompileOptions,
transformsFor as _transformsFor,
registerPlugin,
unregisterPlugin,
} from './lib/system/compile-options';
export { RESOLUTION_MODE_TRANSFORMS, STRICT_MODE_TRANSFORMS } from './lib/plugins/index';
export { EmberPrecompileOptions } from './lib/types';
Expand Down
120 changes: 2 additions & 118 deletions packages/ember-template-compiler/lib/system/compile-options.ts
@@ -1,6 +1,5 @@
import { EMBER_STRICT_MODE } from '@ember/canary-features';
import { assert, deprecate } from '@ember/debug';
import { AST, ASTPlugin, ASTPluginEnvironment, Syntax } from '@glimmer/syntax';
import { assert } from '@ember/debug';
import { RESOLUTION_MODE_TRANSFORMS, STRICT_MODE_TRANSFORMS } from '../plugins/index';
import { EmberPrecompileOptions, PluginFunc } from '../types';
import COMPONENT_NAME_SIMPLE_DASHERIZE_CACHE from './dasherize-component-name';
Expand Down Expand Up @@ -63,127 +62,12 @@ export default function compileOptions(
} else {
let potententialPugins = [...USER_PLUGINS, ...builtInPlugins];
assert('expected plugins', options.plugins);
let providedPlugins = options.plugins.ast.map((plugin) => wrapLegacyPluginIfNeeded(plugin));
let pluginsToAdd = potententialPugins.filter((plugin) => {
assert('expected plugins', options.plugins);
return options.plugins.ast.indexOf(plugin) === -1;
});
options.plugins.ast = providedPlugins.concat(pluginsToAdd);
options.plugins.ast = options.plugins.ast.concat(pluginsToAdd);
}

return options;
}

interface LegacyPlugin {
transform(node: AST.Program): AST.Node;
syntax: Syntax;
}

export type LegacyPluginClass = new (env: ASTPluginEnvironment) => LegacyPlugin;

function isLegacyPluginClass(plugin: PluginFunc | LegacyPluginClass): plugin is LegacyPluginClass {
return plugin.prototype && typeof plugin.prototype.transform === 'function';
}

function wrapLegacyPluginIfNeeded(plugin: PluginFunc | LegacyPluginClass): PluginFunc {
if (isLegacyPluginClass(plugin)) {
const Plugin = plugin;

deprecate(
`Using class based template compilation plugins is deprecated, please update to the functional style: ${Plugin.name}`,
false,
{
id: 'template-compiler.registerPlugin',
until: '4.0.0',
for: 'ember-source',
since: {
enabled: '3.27.0',
},
}
);

const pluginFunc: PluginFunc = (env: ASTPluginEnvironment): ASTPlugin => {
let pluginInstantiated = false;

return {
name: plugin.name,

visitor: {
Program(node: AST.Program): AST.Node | void {
if (!pluginInstantiated) {
pluginInstantiated = true;
let instance = new Plugin(env);

instance.syntax = env.syntax;

return instance.transform(node);
}
},
},
};
};

pluginFunc.__raw = Plugin;

return pluginFunc;
} else {
return plugin;
}
}

export function registerPlugin(type: string, _plugin: PluginFunc | LegacyPluginClass): void {
deprecate(
'registerPlugin is deprecated, please pass plugins directly via `compile` and/or `precompile`.',
false,
{
id: 'template-compiler.registerPlugin',
until: '4.0.0',
for: 'ember-source',
since: {
enabled: '3.27.0',
},
}
);

if (type !== 'ast') {
throw new Error(
`Attempting to register ${_plugin} as "${type}" which is not a valid Glimmer plugin type.`
);
}

for (let i = 0; i < USER_PLUGINS.length; i++) {
let PLUGIN = USER_PLUGINS[i];
if (PLUGIN === _plugin || PLUGIN.__raw === _plugin) {
return;
}
}

let plugin = wrapLegacyPluginIfNeeded(_plugin);

USER_PLUGINS = [plugin, ...USER_PLUGINS];
}

export function unregisterPlugin(type: string, PluginClass: PluginFunc | LegacyPluginClass): void {
deprecate(
'unregisterPlugin is deprecated, please pass plugins directly via `compile` and/or `precompile`.',
false,
{
id: 'template-compiler.registerPlugin',
until: '4.0.0',
for: 'ember-source',
since: {
enabled: '3.27.0',
},
}
);

if (type !== 'ast') {
throw new Error(
`Attempting to unregister ${PluginClass} as "${type}" which is not a valid Glimmer plugin type.`
);
}

USER_PLUGINS = USER_PLUGINS.filter(
(plugin) => plugin !== PluginClass && plugin.__raw !== PluginClass
);
}
11 changes: 7 additions & 4 deletions packages/ember-template-compiler/lib/types.d.ts
Expand Up @@ -4,13 +4,16 @@ import {
builders,
PrecompileOptions,
} from '@glimmer/syntax';
import { LegacyPluginClass } from './system/compile-options';

export type Builders = typeof builders;

export interface PluginFunc extends ASTPluginBuilder<EmberASTPluginEnvironment> {
__raw?: LegacyPluginClass;
}
/*
* It seems like it should be possible to reepxport the `ASTPluginBuilder`
* interface with a new named export, but the I wasn't able to figure out the
* typing. Here export the interface subclass with no modification.
*/
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface PluginFunc extends ASTPluginBuilder<EmberASTPluginEnvironment> {}

interface Plugins {
ast: PluginFunc[];
Expand Down
51 changes: 1 addition & 50 deletions packages/ember-template-compiler/tests/basic-usage-test.js
@@ -1,23 +1,6 @@
import {
_buildCompileOptions,
_preprocess,
_print,
registerPlugin,
unregisterPlugin,
} from '../index';
import { _buildCompileOptions, _preprocess, _print } from '../index';
import { moduleFor, RenderingTestCase } from 'internal-test-helpers';

function reverseElementNodeTag() {
return {
name: 'reverse-element-node-tag',
visitor: {
ElementNode(node) {
node.tag = node.tag.split('').reverse().join('');
},
},
};
}

function removeDataTest() {
return {
name: 'remove-data-test',
Expand All @@ -39,13 +22,6 @@ function removeDataTest() {
moduleFor(
'ember-template-compiler: Embroider-like compilation',
class extends RenderingTestCase {
afterEach() {
expectDeprecation(() => {
unregisterPlugin('ast', removeDataTest);
}, /unregisterPlugin is deprecated, please pass plugins directly via `compile` and\/or `precompile`/);
return super.afterEach();
}

'@test can process a subset of AST plugins and print'(assert) {
let template = '<div data-test="foo" data-blah="derp" class="hahaha">&nbsp;</div>';

Expand All @@ -63,30 +39,5 @@ moduleFor(

assert.equal(result, '<div data-blah="derp" class="hahaha">&nbsp;</div>');
}

'@test registerPlugin based transforms can be avoided'(assert) {
expectDeprecation(() => {
registerPlugin('ast', removeDataTest);
}, /registerPlugin is deprecated, please pass plugins directly via `compile` and\/or `precompile`/);

let template = '<div data-test="foo" data-blah="derp" class="hahaha">&nbsp;</div>';

// build up options including strictMode default values, customizeComponentName, meta.moduleName, etc
let options = _buildCompileOptions({
mode: 'codemod',
moduleName: 'components/foo',
plugins: {
ast: [reverseElementNodeTag],
},
});

let transformedTemplateAST = _preprocess(template, options);

// print back to a handlebars string
let result = _print(transformedTemplateAST, { entityEncoding: 'raw' });

// only reverseElementNodeTag has ran, **not** removeDataTest
assert.equal(result, '<vid data-test="foo" data-blah="derp" class="hahaha">&nbsp;</vid>');
}
}
);
140 changes: 0 additions & 140 deletions packages/ember-template-compiler/tests/system/compile_options_test.js
Expand Up @@ -3,8 +3,6 @@ import {
compileOptions,
RESOLUTION_MODE_TRANSFORMS,
STRICT_MODE_TRANSFORMS,
registerPlugin,
unregisterPlugin,
} from '../../index';
import { moduleFor, AbstractTestCase, RenderingTestCase } from 'internal-test-helpers';

Expand Down Expand Up @@ -49,38 +47,7 @@ moduleFor(
}
);

let customTransformCounter = 0;
class LegacyCustomTransform {
constructor(options) {
customTransformCounter++;
this.options = options;
this.syntax = null;
}

transform(ast) {
let walker = new this.syntax.Walker();

walker.visit(ast, (node) => {
if (node.type !== 'ElementNode') {
return;
}

for (let i = 0; i < node.attributes.length; i++) {
let attribute = node.attributes[i];

if (attribute.name === 'data-test') {
node.attributes.splice(i, 1);
}
}
});

return ast;
}
}

function customTransform() {
customTransformCounter++;

return {
name: 'remove-data-test',

Expand All @@ -98,113 +65,6 @@ function customTransform() {
};
}

class CustomPluginsTests extends RenderingTestCase {
afterEach() {
customTransformCounter = 0;
return super.afterEach();
}

['@test custom plugins can be used']() {
this.render('<div data-test="foo" data-blah="derp" class="hahaha"></div>');
this.assertElement(this.firstChild, {
tagName: 'div',
attrs: { class: 'hahaha', 'data-blah': 'derp' },
content: '',
});
}

['@test wrapped plugins are only invoked once per template'](assert) {
this.render('<div>{{#if this.falsey}}nope{{/if}}</div>');
assert.equal(customTransformCounter, 1, 'transform should only be instantiated once');
}
}

moduleFor(
'ember-template-compiler: [DEPRECATED] registerPlugin with a custom plugins in legacy format',
class extends CustomPluginsTests {
beforeEach() {
expectDeprecation(
`Using class based template compilation plugins is deprecated, please update to the functional style: ${LegacyCustomTransform.name}`
);
expectDeprecation(
'registerPlugin is deprecated, please pass plugins directly via `compile` and/or `precompile`.'
);
registerPlugin('ast', LegacyCustomTransform);
}

afterEach() {
expectDeprecation(() => {
unregisterPlugin('ast', LegacyCustomTransform);
}, /unregisterPlugin is deprecated, please pass plugins directly via `compile` and\/or `precompile`/);
return super.afterEach();
}

['@test custom registered plugins are deduplicated'](assert) {
expectDeprecation(
`Using class based template compilation plugins is deprecated, please update to the functional style: ${LegacyCustomTransform.name}`
);
expectDeprecation(
'registerPlugin is deprecated, please pass plugins directly via `compile` and/or `precompile`.'
);
registerPlugin('ast', LegacyCustomTransform);

this.registerTemplate(
'application',
'<div data-test="foo" data-blah="derp" class="hahaha"></div>'
);
assert.equal(customTransformCounter, 1, 'transform should only be instantiated once');
}
}
);

moduleFor(
'ember-template-compiler: [DEPRECATED] registerPlugin with a custom plugins',
class extends CustomPluginsTests {
beforeEach() {
expectDeprecation(() => {
registerPlugin('ast', customTransform);
}, /registerPlugin is deprecated, please pass plugins directly via `compile` and\/or `precompile`/);
}

afterEach() {
expectDeprecation(() => {
unregisterPlugin('ast', customTransform);
}, /unregisterPlugin is deprecated, please pass plugins directly via `compile` and\/or `precompile`/);

return super.afterEach();
}

['@test custom registered plugins are deduplicated'](assert) {
expectDeprecation(() => {
registerPlugin('ast', customTransform);
}, /registerPlugin is deprecated, please pass plugins directly via `compile` and\/or `precompile`/);

this.registerTemplate(
'application',
'<div data-test="foo" data-blah="derp" class="hahaha"></div>'
);
assert.equal(customTransformCounter, 1, 'transform should only be instantiated once');
}
}
);

moduleFor(
'ember-template-compiler: custom plugins in legacy format passed to compile',
class extends RenderingTestCase {
// override so that we can provide custom AST plugins to compile
compile(templateString) {
expectDeprecation(
'Using class based template compilation plugins is deprecated, please update to the functional style: LegacyCustomTransform'
);
return compile(templateString, {
plugins: {
ast: [LegacyCustomTransform],
},
});
}
}
);

moduleFor(
'ember-template-compiler: custom plugins passed to compile',
class extends RenderingTestCase {
Expand Down

0 comments on commit bbb62dd

Please sign in to comment.