babel-plugin-rewire icon indicating copy to clipboard operation
babel-plugin-rewire copied to clipboard

Error "Cannot read property 'some' of undefined" with "export * from ..."

Open joefiorini opened this issue 9 years ago • 32 comments

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.

joefiorini avatar Dec 09 '15 17:12 joefiorini

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

joefiorini avatar Dec 09 '15 18:12 joefiorini

@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?

joefiorini avatar Dec 10 '15 18:12 joefiorini

@speedskater any thoughts on the above error?

joefiorini avatar Jan 06 '16 15:01 joefiorini

@joefiorini does 1.0.0-beta-4 fix your issue?

speedskater avatar Jan 06 '16 19:01 speedskater

@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).

speedskater avatar Jan 11 '16 14:01 speedskater

ES6 modules are read-only, which is why it doesn't have a setter.

forkingpath avatar Jan 19 '16 22:01 forkingpath

@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.

forkingpath avatar Jan 19 '16 22:01 forkingpath

@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.

speedskater avatar Jan 20 '16 22:01 speedskater

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.

forkingpath avatar Jan 20 '16 23:01 forkingpath

I fixed my issue, so I may have some free time available to try my hand at a PR.

forkingpath avatar Jan 21 '16 02:01 forkingpath

@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.

speedskater avatar Feb 01 '16 08:02 speedskater

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 avatar Feb 07 '16 11:02 erykpiast

@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.

speedskater avatar Feb 07 '16 12:02 speedskater

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.

erykpiast avatar Feb 07 '16 13:02 erykpiast

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 avatar Feb 07 '16 13:02 erykpiast

@erykpiast thanks. You are right finding a solution which works independent of the underlying module system is the way to go.

speedskater avatar Feb 07 '16 14:02 speedskater

Is the Babel bug completely blocking progress on this issue?

idolize avatar Feb 12 '16 01:02 idolize

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 .

erykpiast avatar Feb 12 '16 09:02 erykpiast

@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.

speedskater avatar Mar 06 '16 09:03 speedskater

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];
    }
  });
});

tungv avatar Mar 31 '16 11:03 tungv

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 });

alex-barberi avatar Sep 27 '16 12:09 alex-barberi

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:

screen shot 2016-11-17 at 3 10 53 pm

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>)

screen shot 2016-11-17 at 3 29 28 pm

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 avatar Nov 17 '16 23:11 xveganxxxedgex

@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.

speedskater avatar Nov 21 '16 12:11 speedskater

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 avatar Mar 27 '17 16:03 schtauffen

@schtauffen This is not really a solution.. Still waiting on a proper solution.

Robinfr avatar Jul 27 '17 08:07 Robinfr

I'm seeing what appears to be the same problem. +1 for a proper solution here.

Error: TypeError: Cannot redefine property: __get__

ezmiller avatar Jul 28 '17 14:07 ezmiller

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

dan-kez avatar Jan 20 '18 14:01 dan-kez

I too would love a solution for this. +1

maximus1108 avatar Nov 28 '18 11:11 maximus1108

We face the same problem with multiple export * from 'X' statements in one index.js file.

harpunius avatar Jan 02 '19 13:01 harpunius

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.

WalterWeidner avatar May 07 '19 21:05 WalterWeidner