Skip to content

Commit 700261c

Browse files
author
Lenny Burdette
committedJun 23, 2017
feat(makeDefaultExport): add deprecation message for generated default exports
If a module does not define a default export, loader.js assigns `exports.default = exports` for compatibility with modules that don't use `_interopRequireDefault` from babel6. Mutating exports is unexpected behavior and causes difficult-to-diagnose [bugs][1]. We should remove `makeDefaultExport` in version 5.0. This update * adds a deprecation warning in preparation for removing `makeDefaultExport`. * adds a debug build with the deprecation enabled. Addresses ember-cli#114 [1]:mike-north/ember-lodash#104
1 parent 5ad1976 commit 700261c

File tree

5 files changed

+125
-5
lines changed

5 files changed

+125
-5
lines changed
 

‎build.js

+39-3
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,54 @@ var mkdirp = require('mkdirp').sync;
77

88
mkdirp('./dist/loader');
99
var source = fs.readFileSync('./lib/loader/loader.js', 'utf8');
10+
1011
var instrumented = transform(source, {
11-
plugins: ['transform-es2015-destructuring']
12+
plugins: [
13+
'transform-es2015-destructuring',
14+
['babel-plugin-debug-macros', {
15+
envFlags: {
16+
source: 'env-flags',
17+
flags: { DEBUG: true }
18+
},
19+
debugTools: {
20+
source: 'debug-tools'
21+
}
22+
}]
23+
]
24+
}).code;
25+
26+
var debug = transform(source, {
27+
plugins: [
28+
'transform-es2015-destructuring',
29+
['babel-plugin-debug-macros', {
30+
envFlags: {
31+
source: 'env-flags',
32+
flags: { DEBUG: true }
33+
},
34+
debugTools: {
35+
source: 'debug-tools'
36+
}
37+
}]
38+
]
1239
}).code;
1340

1441
var stripped = transform(source, {
1542
// strip-heimdall *must* come before transpiling destructuring
1643
plugins: [
1744
'babel6-plugin-strip-heimdall',
18-
'transform-es2015-destructuring'
45+
'transform-es2015-destructuring',
46+
['babel-plugin-debug-macros', {
47+
envFlags: {
48+
source: 'env-flags',
49+
flags: { DEBUG: false }
50+
},
51+
debugTools: {
52+
source: 'debug-tools'
53+
}
54+
}]
1955
],
2056
}).code;
2157

2258
fs.writeFileSync('./dist/loader/loader.instrument.js', instrumented);
59+
fs.writeFileSync('./dist/loader/loader.debug.js', debug);
2360
fs.writeFileSync('./dist/loader/loader.js', stripped);
24-

‎lib/loader/loader.js

+36-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { DEBUG } from 'env-flags';
2+
13
var loader, define, requireModule, require, requirejs;
24

35
(function(global) {
@@ -110,12 +112,45 @@ var loader, define, requireModule, require, requirejs;
110112

111113
}
112114

115+
if (DEBUG) {
116+
var deprecationLogger = function () {
117+
console.warn.apply(console, arguments);
118+
};
119+
120+
var constructMakeDefaultExportDeprecation = function (id) {
121+
return 'The `' + id + '` module does not define a default export, but loader.js ' +
122+
'generated one anyway. This behavior is deprecated and will be removed in v5.0.0.';
123+
};
124+
125+
Object.defineProperty(requirejs, 'deprecationLogger', {
126+
enumerable: false,
127+
get() {
128+
return deprecationLogger;
129+
},
130+
set(newLogger) {
131+
deprecationLogger = newLogger;
132+
}
133+
});
134+
}
135+
113136
Module.prototype.makeDefaultExport = function() {
114137
var exports = this.module.exports;
115138
if (exports !== null &&
116139
(typeof exports === 'object' || typeof exports === 'function') &&
117140
exports['default'] === undefined && Object.isExtensible(exports)) {
118-
exports['default'] = exports;
141+
142+
if (DEBUG) {
143+
var id = this.id;
144+
145+
Object.defineProperty(exports, 'default', {
146+
get: function () {
147+
deprecationLogger(constructMakeDefaultExportDeprecation(id));
148+
return exports;
149+
}
150+
});
151+
} else {
152+
exports['default'] = exports;
153+
}
119154
}
120155
};
121156

‎package.json

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"devDependencies": {
1111
"ara": "0.0.3",
1212
"babel-core": "^6.25.0",
13+
"babel-plugin-debug-macros": "^0.1.10",
1314
"babel-plugin-transform-es2015-destructuring": "^6.23.0",
1415
"babel6-plugin-strip-heimdall": "^6.0.1",
1516
"heimdalljs": "^0.3.2",

‎tests/all.js

+42
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,11 @@ test('if factory returns a value it is used as export', function() {
640640
});
641641

642642
test('if a module has no default property assume the return is the default', function() {
643+
var deprecationMessage;
644+
require.deprecationLogger = function(message) {
645+
deprecationMessage = message;
646+
};
647+
643648
define('foo', [], function() {
644649
return {
645650
bar: 'bar'
@@ -664,10 +669,17 @@ test('if a module has no default property assume the return is the default', fun
664669
});
665670

666671
equal(foo.bar, 'bar');
672+
673+
equal(deprecationMessage, 'The `foo` module does not define a default export, but loader.js generated one anyway. This behavior is deprecated and will be removed in v5.0.0.');
667674
});
668675

669676

670677
test('if a CJS style module has no default export assume module.exports is the default', function() {
678+
var deprecationMessage;
679+
require.deprecationLogger = function(message) {
680+
deprecationMessage = message;
681+
};
682+
671683
define('Foo', ['require', 'exports', 'module'], function(require, exports, module) {
672684
module.exports = function Foo() {
673685
this.bar = 'bar';
@@ -692,10 +704,17 @@ test('if a CJS style module has no default export assume module.exports is the d
692704
resolveRelative: 0,
693705
pendingQueueLength: 1
694706
});
707+
708+
equal(deprecationMessage, 'The `Foo` module does not define a default export, but loader.js generated one anyway. This behavior is deprecated and will be removed in v5.0.0.');
695709
});
696710

697711

698712
test('if a module has no default property assume its export is default (function)', function() {
713+
var deprecationMessage;
714+
require.deprecationLogger = function(message) {
715+
deprecationMessage = message;
716+
};
717+
699718
var theFunction = function theFunction() {};
700719
define('foo', ['require', 'exports', 'module'], function() {
701720
return theFunction;
@@ -718,9 +737,16 @@ test('if a module has no default property assume its export is default (function
718737
resolveRelative: 0,
719738
pendingQueueLength: 1
720739
});
740+
741+
equal(deprecationMessage, 'The `foo` module does not define a default export, but loader.js generated one anyway. This behavior is deprecated and will be removed in v5.0.0.');
721742
});
722743

723744
test('if a module has no default property assume its export is default (object)', function() {
745+
var deprecationMessage;
746+
require.deprecationLogger = function(message) {
747+
deprecationMessage = message;
748+
};
749+
724750
var theObject = {};
725751
define('foo', ['require', 'exports', 'module'], function() {
726752
return theObject;
@@ -743,9 +769,16 @@ test('if a module has no default property assume its export is default (object)'
743769
resolveRelative: 0,
744770
pendingQueueLength: 1
745771
});
772+
773+
equal(deprecationMessage, 'The `foo` module does not define a default export, but loader.js generated one anyway. This behavior is deprecated and will be removed in v5.0.0.');
746774
});
747775

748776
test('does not add default if export is frozen', function() {
777+
var deprecationMessage;
778+
require.deprecationLogger = function(message) {
779+
deprecationMessage = message;
780+
};
781+
749782
var theObject = Object.freeze({});
750783
define('foo', ['require', 'exports', 'module'], function() {
751784
return theObject;
@@ -768,9 +801,16 @@ test('does not add default if export is frozen', function() {
768801
resolveRelative: 0,
769802
pendingQueueLength: 1
770803
});
804+
805+
equal(deprecationMessage, undefined);
771806
});
772807

773808
test('does not add default if export is sealed', function() {
809+
var deprecationMessage;
810+
require.deprecationLogger = function(message) {
811+
deprecationMessage = message;
812+
};
813+
774814
var theObject = Object.seal({ derp: {} });
775815
define('foo', ['require', 'exports', 'module'], function() {
776816
return theObject;
@@ -793,6 +833,8 @@ test('does not add default if export is sealed', function() {
793833
resolveRelative: 0,
794834
pendingQueueLength: 1
795835
});
836+
837+
equal(deprecationMessage, undefined);
796838
});
797839

798840
test('has good error message for missing module', function() {

‎yarn.lock

+7-1
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,12 @@ babel-plugin-dead-code-elimination@^1.0.2:
230230
version "1.0.2"
231231
resolved "https://registry.yarnpkg.com/babel-plugin-dead-code-elimination/-/babel-plugin-dead-code-elimination-1.0.2.tgz#5f7c451274dcd7cccdbfbb3e0b85dd28121f0f65"
232232

233+
babel-plugin-debug-macros@^0.1.10:
234+
version "0.1.10"
235+
resolved "https://npm.vip.global.square/babel-plugin-debug-macros/-/babel-plugin-debug-macros-0.1.10.tgz#dd077ad6e1cc0a8f9bbc6405c561392ebfc9a01c"
236+
dependencies:
237+
semver "^5.3.0"
238+
233239
babel-plugin-eval@^1.0.1:
234240
version "1.0.1"
235241
resolved "https://registry.yarnpkg.com/babel-plugin-eval/-/babel-plugin-eval-1.0.1.tgz#a2faed25ce6be69ade4bfec263f70169195950da"
@@ -1962,7 +1968,7 @@ rsvp@~3.2.1:
19621968
version "3.2.1"
19631969
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.2.1.tgz#07cb4a5df25add9e826ebc67dcc9fd89db27d84a"
19641970

1965-
semver@^5.1.0:
1971+
semver@^5.1.0, semver@^5.3.0:
19661972
version "5.3.0"
19671973
resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
19681974

0 commit comments

Comments
 (0)