babel-plugin-rewire
babel-plugin-rewire copied to clipboard
Error "Cannot read property 'some' of undefined" with "export * from ..."
I have a number of files in my codebase that use export * from '...'
to export all imported dependencies. This breaks the latest beta saying that node.specifiers
is undefined at line 62 of the transpiled babel-plugin-rewire.js
, which corresponds to line 60 of the non-transpiled source.
I opened #79, which fixes the parsing error, but I still get a runtime error when I try to run code with mixed export types. Ie. The following code:
import entities from './entities';
import fields from './fields';
import reduxForm from './reduxForm';
export default {
entities,
reduxForm,
fields,
};
export * from './entities';
export * from './reduxForm';
export * from './fields';
produces the following runtime error:
/Users/joe/Code/LendingHome-monolith/ops/client/src/toolkits-entities/reducers/index.js:199
exports.__get__ = _get__;
^
TypeError: Cannot set property __get__ of #<Object> which has only a getter
at Object.<anonymous> (index.js:9:2)
at Module._compile (module.js:425:26)
at loader (/Users/joe/Code/LendingHome-monolith/ops/node_modules/babel-register/lib/node.js:130:5)
at Object.require.extensions.(anonymous function) [as .js] (/Users/joe/Code/LendingHome-monolith/ops/node_modules/babel-register/lib/node.js:140:7)
...snip
@speedskater I'm trying to reproduce this error with a test, but I'm running into an issue. I added a test to usage-tests/BabelRewirePluginUsageTest.js
that uses a wildcard export, but when I run it with npm test
I get the following error:
/Users/joe/Code/Projects/babel-plugin-rewire/samples/wildcardExport/src/wildcardExport.js:3
import _Object$defineProperty from 'babel-runtime/core-js/object/define-property';
^^^^^^
SyntaxError: Unexpected token import
at exports.runInThisContext (vm.js:53:16)
at Module._compile (module.js:404:25)
at Object.Module._extensions.(anonymous function) [as .js] (/Users/joe/Code/Projects/babel-plugin-rewire/node_modules/node-hook/index.js:52:14)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:311:12)
at Module.require (module.js:366:17)
at require (module.js:385:17)
at Object.<anonymous> (/Users/joe/Code/Projects/babel-plugin-rewire/samples/wildcardExport/sample.js:16:23)
at Module._compile (module.js:425:26)
at Object.Module._extensions.(anonymous function) [as .js] (/Users/joe/Code/Projects/babel-plugin-rewire/node_modules/node-hook/index.js:52:14)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:311:12)
at Module.require (module.js:366:17)
at require (module.js:385:17)
at Object.<anonymous> (/Users/joe/Code/Projects/babel-plugin-rewire/usage-tests/BabelRewirePluginUsageTest.js:67:1)
Just to try to isolate the problem, I added rewire to the babelrc and ran mocha --compilers js:babel-register samples/wildcardExport/sample.js
and I got a different error.
I've pushed my test additions to a tmp branch on my fork at https://github.com/joefiorini/babel-plugin-rewire/tree/tmp. Any ideas what I might be doing wrong?
@speedskater any thoughts on the above error?
@joefiorini does 1.0.0-beta-4 fix your issue?
@joefiorini I see the problem as well as the error potential. But to fix the problem won't be any easy task. But I have an idea how to solve it and will tackle it on Feburary the 1st (sorry for the delay but then i will have again a whole day dedicated for babel-plugin-rewire).
ES6 modules are read-only, which is why it doesn't have a setter.
@speedskater would you be willing to outline your idea? i'm stuck on this incompatibility between ES6 modules and mocking libraries and I don't know how to proceed, so I would love to create a PR if it means I can use this plugin to make unit tests.
@karlnp thanks for your feedback. The idea is to add an additional library to each es6 module and use this library to register all dependencies which can be rewired in this module. The next step would be in your test to import this helper library and use calls exported on this library to actually rewire the needed dependencies. My biggest issue with this idea at the moment is. That I have currently no idea how to uniquely identify a module. (relative/absolute paths)
in the end rewiring could then work like this (naive idea;) ):
import { getRewireAPI } from 'rewireHelpers.js'
getRewireAPI('fileToRewire').__set__('myVariableToMock', mock);
I hope I could explain my idea a bit. If you want to know further details or something is unclear do not hesitate to ask. If you could help with a PR in this case this would be just awesome.
Well, I know that @logansfmyth wanted some feedback on this: https://www.npmjs.com/package/babel-plugin-transform-module-exports-reflection so it might give you some insights or a head start - I haven't gotten to implementing it yet.
I fixed my issue, so I may have some free time available to try my hand at a PR.
@karlnp sorry for the late reply and thanks for your offer. I have had a look at babel-plugin-transform-module-exports-reflection but it seems that it does exactly the same as this plugin. I am investigating some ideas of how to resolve this issue and will let you know later on.
I've just encountered this problem and what I see is:
Currently all exports from module you want to reexport are assigned to exports
object of "reexporter" module, including properties added by Rewire. So when you try to add those things again, error is thrown.
The easiest solution I found is to filter those properties when reexporting. But until reexporting is handled by Babel itself it doesn't seem possible, so we may let them to be assigned and then we may override them using Object.defineProperty
syntax (instead of object.prop =
which triggers getter/setter interface). This approach lets to suppress an error, keeping doing what we want to do, but I'm not sure if it's perfect.
@erykpiast thanks for your suggestion. I am not 100% sure if i understood your suggestion. Could you please provide a small code sample.
I have already implemented a feature which filters all wildcard imports. I will try to use the technique for reexporting, but i am not sure, whether this makes sense in combination with lazy module evaluation. We will just have to try.
I've just added MWE for this issue: https://github.com/speedskater/babel-plugin-rewire/pull/96. What I'm proposing is to use Object.defineProperty
(like in addPropertyToAPIObject
runtime function) instead of creating exports
object using regular property assignment (ex. exports.__get__ = __get__
). I'm working on it now, will see if it's valid solution.
Ok, I can see it now... exports.__get__ = __get__
is generated by Babel from export { __get__ }
added by Rewire. Until we don't make assumption that exports
object exists in module scope (I guess we don't want to do it), we can't use this Object.defineProperty
approach.
It's worth to check if it's generic Babel issue, I mean if the error occurs when you export function already exported by module you're reexporting. UPDATE: yes, it is. I'll fill and issue regarding this.
UPDATE 2: it's already there: https://phabricator.babeljs.io/T2438.
@erykpiast thanks. You are right finding a solution which works independent of the underlying module system is the way to go.
Is the Babel bug completely blocking progress on this issue?
I think so.
2016-02-12 2:10 GMT+01:00 David Idol [email protected]:
Is the Babel bug completely blocking progress on this issue?
— Reply to this email directly or view it on GitHub https://github.com/speedskater/babel-plugin-rewire/issues/78#issuecomment-183138177 .
@joefiorini, @idolize , @erykpiast, @karlnp sorry that we are stuck in this matter but we first try to ship a new version of the plugin including babel 6 support and will start than about finding a solution. how we can getting around polluting existing exports. We had a discussion about the next steps in the gitter chat (https://gitter.im/speedskater/babel-plugin-rewire). Maybe we should discuss our ideas there and find a way to bring the project forward and get around issues like this one.
I have the same issue with export * from 'some modules'
. This is the following code that I use:
export * from './icon-menu/icon-menu';
export * from './menu-item/menu-item';
and my .babelrc
:
{
"presets": ["es2015", "react", "stage-0"],
"plugins": [
[
"transform-decorators-legacy",
"syntax-do-expressions",
"transform-runtime"
],
["babel-plugin-module-alias", [
{ "src": "./src", "expose": "src" }
]],
["typecheck", {
"disable": {
"production": true
}
}]
],
"env": {
"development": {
"plugins": [
["lodash"],
["react-transform", {
"transforms": [{
"transform": "react-transform-hmr",
"imports": ["react"],
"locals": ["module"]
}, {
"transform": "react-transform-catch-errors",
"imports": ["react", "redbox-react"]
}]
}]
]
},
"production": {
"plugins": [
["lodash"]
]
},
"test": {
"plugins": [
["rewire"],
]
}
}
}
The error I got
TypeError: Cannot redefine property: __get__
at Function.defineProperty (native)
at _loop2 (/Users/tungvu/projects/adatao/pInsights/utils/src/arimo-ui/components/menus/index.js:29:10)
at Object.<anonymous> (/Users/tungvu/projects/adatao/pInsights/utils/src/arimo-ui/components/menus/index.js:38:15)
This is the generated code from babel-loaders
:
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _iconMenu = require('./icon-menu/icon-menu');
Object.keys(_iconMenu).forEach(function (key) {
if (key === "default") return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function get() {
return _iconMenu[key];
}
});
});
var _menuItem = require('./menu-item/menu-item');
Object.keys(_menuItem).forEach(function (key) {
if (key === "default") return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function get() {
return _menuItem[key];
}
});
});
I'm getting exactly the same generated code as @tungv above.
I'm getting this error:
Cannot read property 'defineProperty' of undefined
The error shows up here:
Object.defineProperty(exports, "__esModule", { value: true });
I'm having the same issue, does anyone have a workaround solution? It looks like it doesn't have issues handling the first exported module, but it starts having trouble on the second:
My app works fine in the browser, but I'm unable to get my tests to run due to this multiple exports issue. I get this error in my test response:
TypeError: Attempting to change the getter of an unconfigurable property.
And running the tests in browser I get:
Uncaught TypeError: Cannot redefine property: __get__ at Function.defineProperty (<anonymous>)
This is what I have in my .babelrc:
{
"presets": ["latest", "react", "stage-0"],
"plugins": ["transform-decorators-legacy"],
"env": {
"test": {
"plugins": [
["./babel-plugins/remove-decorators", ["root", "branch"]],
"rewire"
]
}
}
}
@xveganxxxedgex currently their is no workaround for multiple wildcard exports but we are started to move in this direction. First part of it is a global store for all dependencies added in 1.1.0-alpha. The next steps will be harder as we have to add different switches to allow different kind of export options for accessing the rewire api for a single module.
In case anyone else has run into this issue, the workaround is to switch from wildcard exports to explicit exports.
export * from './my-awesome-utils'
becomes:
export { getDocHeight, util2, etc } from './my-awesome-utils'
Hopefully the fix for this issue is still planned :)
@schtauffen This is not really a solution.. Still waiting on a proper solution.
I'm seeing what appears to be the same problem. +1 for a proper solution here.
Error:
TypeError: Cannot redefine property: __get__
I'm also waiting on a proper solution for this and am unlikely to be able use this library until it's fixed. We are presently using the export * from '...'
on in our index.js
files to export api functionality from multiple files.
@schtauffen comment is a temporary workaround
I too would love a solution for this. +1
We face the same problem with multiple export * from 'X'
statements in one index.js
file.
Bump. This is a pretty major limitation of the library. We're using this in some of our other repos that are more greenfield but can't make use of Rewire in our older code because it uses star exports.