Skip to content

Commit 94ce290

Browse files
author
Robert Jackson
committed
Add debug tooling babel plugins.
1 parent 12945fb commit 94ce290

5 files changed

Lines changed: 236 additions & 26 deletions

File tree

README.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,58 @@ treeForAddon(tree) {
9595
}
9696
```
9797

98+
### Debug Tooling
99+
100+
In order to allow addons to easily provide good development mode ergonomics (assertions, deprecations, etc) but
101+
still perform well in production mode ember-cli-babel automatically manages stripping / removing certain debug
102+
statements. This concept was originally proposed in [ember-cli/rfcs#50](https://github.com/ember-cli/rfcs/pull/50),
103+
but has been slightly modified during implementation (after researching what works well and what does not).
104+
105+
#### Debug Macros
106+
107+
To add convienient deprecations and assertions, consumers (apps and/or addons) can do the following:
108+
109+
```js
110+
import { deprecate, assert } from '@ember/debug';
111+
112+
export default Ember.Component.extend({
113+
init() {
114+
this._super(...arguments);
115+
deprecate(
116+
'Passing a string value or the `sauce` parameter is deprecated, please pass an instance of Sauce instead',
117+
false,
118+
{ until: '1.0.0', id: 'some-addon-sauce' }
119+
);
120+
assert('You must provide sauce for x-awesome.', this.sauce);
121+
}
122+
})
123+
```
124+
125+
In testing and development environments those statements will be executed (and assert or deprecate as appropriate), but
126+
in production builds they will be inert (and stripped during minification).
127+
128+
#### General Purpose Env Flags
129+
130+
In some cases you may have the need to do things in debug builds that isn't related to asserts/deprecations/etc. For
131+
example, you may expose certain API's for debugging only. You can do that via the `DEBUG` environment flag:
132+
133+
```js
134+
import { DEBUG } from '@glimmer/env';
135+
136+
const Component = Ember.Component.extend();
137+
138+
if (DEBUG) {
139+
Component.reopen({
140+
specialMethodForDebugging() {
141+
// do things ;)
142+
}
143+
});
144+
}
145+
```
146+
147+
In testing and development environments `DEBUG` will be replaced by the boolean literal `true`, and in production builds it will be
148+
replaced by `false`. When ran through a minifier (with dead code elimination) the entire section will be stripped.
149+
98150
### About Modules
99151

100152
Older versions of Ember CLI (`< 2.12`) use its own ES6 module transpiler. Because of that, this plugin disables Babel

index.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ module.exports = {
176176

177177
options.plugins = [].concat(
178178
userPlugins,
179+
this._getDebugMacroPlugins(config),
179180
shouldCompileModules && this._getModulesPlugin(),
180181
this._getPresetEnvPlugins(addonProvidedConfig),
181182
userPostTransformPlugins
@@ -191,6 +192,32 @@ module.exports = {
191192
return options;
192193
},
193194

195+
_getDebugMacroPlugins(config) {
196+
let addonOptions = config['ember-cli-babel'] || {};
197+
198+
if (addonOptions.disableDebugTooling) { return; }
199+
200+
const DebugMacros = require('babel-plugin-debug-macros').default;
201+
const isProduction = process.env.EMBER_ENV === 'production';
202+
203+
let options = {
204+
envFlags: {
205+
source: '@glimmer/env',
206+
flags: { DEBUG: !isProduction, CI: !!process.env.CI }
207+
},
208+
209+
externalizeHelpers: {
210+
global: 'Ember'
211+
},
212+
213+
debugTools: {
214+
source: '@ember/debug'
215+
}
216+
};
217+
218+
return [[DebugMacros, options]];
219+
},
220+
194221
_getPresetEnvPlugins(config) {
195222
let options = config.options;
196223

node-tests/addon-test.js

Lines changed: 140 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,17 @@ const CoreObject = require('core-object');
77
const AddonMixin = require('../index');
88
const path = require('path');
99
const resolve = require('resolve');
10+
const CommonTags = require('common-tags');
11+
const stripIndent = CommonTags.stripIndent;
1012
const BroccoliTestHelper = require('broccoli-test-helper');
1113
const createBuilder = BroccoliTestHelper.createBuilder;
1214
const createTempDir = BroccoliTestHelper.createTempDir;
1315

1416
let Addon = CoreObject.extend(AddonMixin);
1517

1618
describe('ember-cli-babel', function() {
19+
const ORIGINAL_EMBER_ENV = process.env.EMBER_ENV;
20+
1721
beforeEach(function() {
1822
this.ui = new MockUI();
1923
let project = { root: __dirname };
@@ -24,6 +28,14 @@ describe('ember-cli-babel', function() {
2428
});
2529
});
2630

31+
afterEach(function() {
32+
if (ORIGINAL_EMBER_ENV === undefined) {
33+
delete process.env.EMBER_ENV;
34+
} else {
35+
process.env.EMBER_ENV = ORIGINAL_EMBER_ENV;
36+
}
37+
});
38+
2739
describe('transpileTree', function() {
2840
this.timeout(50000);
2941

@@ -33,8 +45,6 @@ describe('ember-cli-babel', function() {
3345

3446
beforeEach(co.wrap(function* () {
3547
input = yield createTempDir();
36-
subject = this.addon.transpileTree(input.path());
37-
output = createBuilder(subject);
3848
}));
3949

4050
afterEach(co.wrap(function* () {
@@ -48,6 +58,9 @@ describe('ember-cli-babel', function() {
4858
"bar.js": `let bar = () => {};`
4959
});
5060

61+
subject = this.addon.transpileTree(input.path());
62+
output = createBuilder(subject);
63+
5164
yield output.build();
5265

5366
expect(
@@ -57,6 +70,131 @@ describe('ember-cli-babel', function() {
5770
"foo.js": `var foo = function foo() {};`,
5871
});
5972
}));
73+
74+
describe('debug macros', function() {
75+
it("can opt-out via ember-cli-babel.disableDebugTooling", co.wrap(function* () {
76+
process.env.EMBER_ENV = 'development';
77+
78+
let contents = stripIndent`
79+
import { DEBUG } from '@glimmer/env';
80+
if (DEBUG) {
81+
console.log('debug mode!');
82+
}
83+
`;
84+
85+
input.write({
86+
"foo.js": contents
87+
});
88+
89+
subject = this.addon.transpileTree(input.path(), {
90+
'ember-cli-babel': {
91+
disableDebugTooling: true
92+
}
93+
});
94+
95+
output = createBuilder(subject);
96+
97+
yield output.build();
98+
99+
expect(
100+
output.read()
101+
).to.deep.equal({
102+
"foo.js": contents
103+
});
104+
}));
105+
106+
describe('in development', function() {
107+
it("should replace env flags by default ", co.wrap(function* () {
108+
process.env.EMBER_ENV = 'development';
109+
110+
input.write({
111+
"foo.js": stripIndent`
112+
import { DEBUG } from '@glimmer/env';
113+
if (DEBUG) { console.log('debug mode!'); }
114+
`
115+
});
116+
117+
subject = this.addon.transpileTree(input.path());
118+
output = createBuilder(subject);
119+
120+
yield output.build();
121+
122+
expect(
123+
output.read()
124+
).to.deep.equal({
125+
"foo.js": `\nif (true) {\n console.log('debug mode!');\n}`
126+
});
127+
}));
128+
129+
it("should replace debug macros by default ", co.wrap(function* () {
130+
process.env.EMBER_ENV = 'development';
131+
132+
input.write({
133+
"foo.js": stripIndent`
134+
import { assert } from '@ember/debug';
135+
assert('stuff here', isNotBad());
136+
`
137+
});
138+
139+
subject = this.addon.transpileTree(input.path());
140+
output = createBuilder(subject);
141+
142+
yield output.build();
143+
144+
expect(
145+
output.read()
146+
).to.deep.equal({
147+
"foo.js": `(true && Ember.assert('stuff here', isNotBad()));`
148+
});
149+
}));
150+
});
151+
152+
describe('in production', function() {
153+
it("should replace env flags by default ", co.wrap(function* () {
154+
process.env.EMBER_ENV = 'production';
155+
156+
input.write({
157+
"foo.js": stripIndent`
158+
import { DEBUG } from '@glimmer/env';
159+
if (DEBUG) { console.log('debug mode!'); }
160+
`
161+
});
162+
163+
subject = this.addon.transpileTree(input.path());
164+
output = createBuilder(subject);
165+
166+
yield output.build();
167+
168+
expect(
169+
output.read()
170+
).to.deep.equal({
171+
"foo.js": `\nif (false) {\n console.log('debug mode!');\n}`
172+
});
173+
}));
174+
175+
it("should replace debug macros by default ", co.wrap(function* () {
176+
process.env.EMBER_ENV = 'production';
177+
178+
input.write({
179+
"foo.js": stripIndent`
180+
import { assert } from '@ember/debug';
181+
assert('stuff here', isNotBad());
182+
`
183+
});
184+
185+
subject = this.addon.transpileTree(input.path());
186+
output = createBuilder(subject);
187+
188+
yield output.build();
189+
190+
expect(
191+
output.read()
192+
).to.deep.equal({
193+
"foo.js": `(false && Ember.assert('stuff here', isNotBad()));`
194+
});
195+
}));
196+
});
197+
});
60198
});
61199

62200
describe('_getAddonOptions', function() {

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
},
3737
"dependencies": {
3838
"amd-name-resolver": "0.0.6",
39+
"babel-plugin-debug-macros": "^0.1.6",
3940
"babel-plugin-transform-es2015-modules-amd": "^6.24.0",
4041
"babel-polyfill": "^6.16.0",
4142
"babel-preset-env": "^1.2.0",
@@ -49,6 +50,7 @@
4950
"broccoli-test-helper": "^1.1.0",
5051
"chai": "^3.5.0",
5152
"co": "^4.6.0",
53+
"common-tags": "^1.4.0",
5254
"console-ui": "^1.0.2",
5355
"core-object": "^2.0.6",
5456
"ember-cli": "^2.6.2",

yarn.lock

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,6 @@ ast-types@0.8.12:
168168
version "0.8.12"
169169
resolved "https://registry.npmjs.org/ast-types/-/ast-types-0.8.12.tgz#a0d90e4351bb887716c83fd637ebf818af4adfcc"
170170

171-
ast-types@0.8.15:
172-
version "0.8.15"
173-
resolved "https://registry.npmjs.org/ast-types/-/ast-types-0.8.15.tgz#8eef0827f04dff0ec8857ba925abe3fea6194e52"
174-
175171
ast-types@0.9.6:
176172
version "0.9.6"
177173
resolved "https://registry.npmjs.org/ast-types/-/ast-types-0.9.6.tgz#102c9e9e9005d3e7e3829bf0c4fa24ee862ee9b9"
@@ -428,6 +424,12 @@ babel-plugin-dead-code-elimination@^1.0.2:
428424
version "1.0.2"
429425
resolved "https://registry.npmjs.org/babel-plugin-dead-code-elimination/-/babel-plugin-dead-code-elimination-1.0.2.tgz#5f7c451274dcd7cccdbfbb3e0b85dd28121f0f65"
430426

427+
babel-plugin-debug-macros@^0.1.6:
428+
version "0.1.6"
429+
resolved "https://registry.yarnpkg.com/babel-plugin-debug-macros/-/babel-plugin-debug-macros-0.1.6.tgz#6e0a29c6f3c3e122a8bd6fdb41fc2475d8f894ce"
430+
dependencies:
431+
semver "^5.3.0"
432+
431433
babel-plugin-eval@^1.0.1:
432434
version "1.0.1"
433435
resolved "https://registry.npmjs.org/babel-plugin-eval/-/babel-plugin-eval-1.0.1.tgz#a2faed25ce6be69ade4bfec263f70169195950da"
@@ -1395,6 +1397,12 @@ commander@2.9.0, commander@^2.5.0, commander@^2.6.0:
13951397
dependencies:
13961398
graceful-readlink ">= 1.0.0"
13971399

1400+
common-tags@^1.4.0:
1401+
version "1.4.0"
1402+
resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.4.0.tgz#1187be4f3d4cf0c0427d43f74eef1f73501614c0"
1403+
dependencies:
1404+
babel-runtime "^6.18.0"
1405+
13981406
commoner@~0.10.3:
13991407
version "0.10.8"
14001408
resolved "https://registry.npmjs.org/commoner/-/commoner-0.10.8.tgz#34fc3672cd24393e8bb47e70caa0293811f4f2c5"
@@ -3807,22 +3815,14 @@ qs@6.4.0, qs@^6.2.0, qs@~6.4.0:
38073815
version "6.4.0"
38083816
resolved "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
38093817

3810-
quick-temp@0.1.6:
3818+
quick-temp@0.1.6, quick-temp@^0.1.2, quick-temp@^0.1.3, quick-temp@^0.1.5:
38113819
version "0.1.6"
38123820
resolved "https://registry.npmjs.org/quick-temp/-/quick-temp-0.1.6.tgz#a6242a15cba9f9cdbd341287b5c569e318eec307"
38133821
dependencies:
38143822
mktemp "~0.4.0"
38153823
rimraf "~2.2.6"
38163824
underscore.string "~2.3.3"
38173825

3818-
quick-temp@^0.1.2, quick-temp@^0.1.3, quick-temp@^0.1.5:
3819-
version "0.1.8"
3820-
resolved "https://registry.npmjs.org/quick-temp/-/quick-temp-0.1.8.tgz#bab02a242ab8fb0dd758a3c9776b32f9a5d94408"
3821-
dependencies:
3822-
mktemp "~0.4.0"
3823-
rimraf "^2.5.4"
3824-
underscore.string "~3.3.4"
3825-
38263826
qunit-notifications@^0.1.1:
38273827
version "0.1.1"
38283828
resolved "https://registry.npmjs.org/qunit-notifications/-/qunit-notifications-0.1.1.tgz#3001afc6a6a77dfbd962ccbcddde12dec5286c09"
@@ -3895,7 +3895,7 @@ readdirp@^2.0.0:
38953895
readable-stream "^2.0.2"
38963896
set-immediate-shim "^1.0.1"
38973897

3898-
recast@0.10.33:
3898+
recast@0.10.33, recast@^0.10.10:
38993899
version "0.10.33"
39003900
resolved "https://registry.npmjs.org/recast/-/recast-0.10.33.tgz#942808f7aa016f1fa7142c461d7e5704aaa8d697"
39013901
dependencies:
@@ -3904,15 +3904,6 @@ recast@0.10.33:
39043904
private "~0.1.5"
39053905
source-map "~0.5.0"
39063906

3907-
recast@^0.10.10:
3908-
version "0.10.43"
3909-
resolved "https://registry.npmjs.org/recast/-/recast-0.10.43.tgz#b95d50f6d60761a5f6252e15d80678168491ce7f"
3910-
dependencies:
3911-
ast-types "0.8.15"
3912-
esprima-fb "~15001.1001.0-dev-harmony-fb"
3913-
private "~0.1.5"
3914-
source-map "~0.5.0"
3915-
39163907
recast@^0.11.17, recast@^0.11.3:
39173908
version "0.11.23"
39183909
resolved "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz#451fd3004ab1e4df9b4e4b66376b2a21912462d3"
@@ -4633,7 +4624,7 @@ ultron@1.0.x:
46334624
version "1.0.2"
46344625
resolved "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa"
46354626

4636-
underscore.string@^3.2.2, underscore.string@~3.3.4:
4627+
underscore.string@^3.2.2:
46374628
version "3.3.4"
46384629
resolved "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.4.tgz#2c2a3f9f83e64762fdc45e6ceac65142864213db"
46394630
dependencies:

0 commit comments

Comments
 (0)