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

[CLEANUP beta] Remove template-compiler.registerPlugin #19704

Merged
merged 1 commit into from Aug 22, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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