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

Attempting to define property on object that is not extensible #28

Closed
0x80 opened this issue Aug 6, 2015 · 34 comments
Closed

Attempting to define property on object that is not extensible #28

0x80 opened this issue Aug 6, 2015 · 34 comments

Comments

@0x80
Copy link

0x80 commented Aug 6, 2015

I'm now trying to work with a Karma Webpack setup, and without even trying to mock anything I get the following error from my tests:

INFO [karma]: Karma v0.12.37 server started at http://localhost:9876/
INFO [launcher]: Starting browser PhantomJS
INFO [PhantomJS 1.9.8 (Mac OS X 0.0.0)]: Connected on socket FV664eyGWLxApd_KTvrr with id 51361345
PhantomJS 1.9.8 (Mac OS X 0.0.0) ERROR
  TypeError: Attempting to define property on object that is not extensible.
  at /Users/me/myproject/app/components/__tests__/Something_test.js:26431

Any idea what might be wrong? I'm using babel 5.8 and webpack 1.10

I've set the webpack config to debug: 'inline-source-maps' but the line number from the error is not referencing the original souce. It's outside of the scope of this issue but if someone can give me advise on how to fix that I'd appreciate it :)

@speedskater
Copy link
Owner

@0x80 I think the error is regression of making the export properties not enumerable. I would suggest to try to use babel-plugin-rewire version 0.1.12 in the mean time. If this does not fix your error could please provide a usage sample as a PR ?

@0x80
Copy link
Author

0x80 commented Aug 6, 2015

@speedskater with that version I'm getting a different error in my tests: TypeError: 'undefined' is not a function (evaluating '__$Setters__[name](value)')

And if I use the app code in a browser with the plugin on the loader I see Uncaught TypeError: __$Getters__[name] is not a function

I'm going to be on a holliday in about two hours and I'm afraid I won't be able to provide a good sample as a PR before then...

@speedskater
Copy link
Owner

Okay. Thank you I will try to fix the problem asap. But it will take at least till tomorrow. So have a nice holliday and hopefully the bug is fixed afterwards :)

@0x80
Copy link
Author

0x80 commented Aug 6, 2015

👍

@elicwhite
Copy link
Contributor

I ran into this problem when building rewire-global because of modules that were returning things like booleans which you can obviously not add properties to.

The fix that worked for me was to selectively expose the rewire functionality on modules that made sense to rewire at all: https://github.com/TheSavior/rewire-global/blob/master/index.js#L11

@speedskater
Copy link
Owner

@TheSavior thanks for your suggestion. I think the problem should be solved by converting the primitive types to real objects.
@0x80 I thinks you can circumvent the problem by changing the exported primitive to a real object. e.g.

see: https://javascriptweblog.wordpress.com/2010/09/27/the-secret-life-of-javascript-primitives/

Will tackle the problem today evening.

@elicwhite
Copy link
Contributor

It feels super sketchy to convert people's primitives to objects. And as the article mentions, that won't work for booleans.

With the basic rewire library, not every module has the get and set added, only the files that are explicitly called with rewire('module/path') have it added at runtime. This means that the user has control over what gets added.

Using rewireify, rewire-global, or babel-plugin-rewire means that every module at compile time is converted and then the user only uses specific files. That means that modules the user has no intention of ever looking into still need to work just as they would without rewire.

IMHO, It is better to only add the rewire functions to modules the user might potentially want to rewire instead of modifying potential logic and behavior (converting the primitives to objects) in every module.

@speedskater
Copy link
Owner

I am just preparing. It is based on http://www.2ality.com/2011/04/javascript-converting-any-value-to.html. Thanks for your hint regarding boolean values. For boolean values I will use the normal assignment with standard properties. It has the drawback that enumerable properties are exported in this case but at least it should work.

Although I agree with you that changing only the code which is actually rewired would be nicer i think it is currently not possible. I think to achieve this a major rewrite would be required.

@elicwhite
Copy link
Contributor

I guess I am making the claim that nobody ever wants to rewire modules that export primitives. So only adding the rewire methods on things that export functions and objects is safer than modifying possible behavior of people's code by converting the primitives up to objects.

@speedskater
Copy link
Owner

@TheSavior I have just run into another issue and i think you are definitely right. Will publish the fix in some hours :).

@speedskater
Copy link
Owner

@TheSavior, @0x80 The Problem should be fixed in the latest version 0.1.14. Only default exports which are of type function or object will get the rewire properties attached. Could you please let me know if the fix works for you.

@kibin
Copy link

kibin commented Oct 5, 2015

That’s still issue for me. I’m trying to use it with karma and before I’m able to do anything I get

 PhantomJS 2.0.0 (Mac OS X 0.0.0)
          10) TypeError: undefined is not a constructor (evaluating '__$Getters__[name]()') in http://localhost:9876/base/tests.webpack.js?2d9ea7e187cd4e771e0f48bb55354ba0e32164be (line 57399)

My tests.webpack.js is dumb and simple:

var testsContent = require.context('./frontend/tests', true);

testsContent.keys().forEach(testsContent);

Version of plugin: babel-plugin-rewire@0.1.22 node_modules/babel-plugin-rewire

Am I missing something?

UPD: I tried to switch to Chrome and get new error:

Chrome 45.0.2454 (Mac OS X 10.10.5)
          1) TypeError: __$Setters__[name] is not a function

@kibin
Copy link

kibin commented Oct 5, 2015

I placed a debugger in function __Rewire__ and discovered that name in arguments is undefined.

@fobdy
Copy link

fobdy commented Oct 20, 2015

I think this issue has to be reopened. We have the similar problem with webpack, babel, redux and babel-plugin-rewire@0.1.22 :(

Uncaught TypeError: __$Getters__[name] is not a function

@speedskater
Copy link
Owner

@fobdy Thanks for reopening the issue. Could you please test it with 0.1.23-beta-3 ?

@jorispz
Copy link

jorispz commented Oct 21, 2015

I ran into the same problem today - webpack, babel, redux, and babel-plugin-rewire@0.1.23-beta3. Unfortunately the issue isn't solved for us in this beta-3 release, we get the same error:

__$Setters__[name] is not a function

Please let me know if there's anything I can do to assist in debugging!

@speedskater
Copy link
Owner

@jorispz thanks for testing. It would be great if you could create a PR with a sample, which reconstructs your problem. I will then try to fix it as soon as possible.

@CrazyUmka
Copy link
Contributor

Here is example of issue with redux, babel, webpack demonstration: https://github.com/CrazyUmka/babel-plugin-rewire-issue28

Please reopen the issue (now it is in closed status)

@elicwhite
Copy link
Contributor

Thanks for providing a sample. Is it possible for you to reduce the test case down to the smallest part that reproduces the error? And it doesn't look like your repo has a test suite that we can run to reproduce the error.

If you find that setting up that repo for this is too difficult, you might want to consider adding a fixture to this repo and adding a failing test here for us to fix.

@jorispz
Copy link

jorispz commented Oct 22, 2015

I created a minimal testcase here: https://github.com/jorispz/babel-plugin-rewire-issue-28

As explained in the README, the problem can be reproduced by running 'npm run test', and disappears when not using the rewire plugin. The cause seems to be the use of Object.assign - see README for details.

I hope this helps, let me know if I can help further!

@joelclimbsthings
Copy link

+1
We're also unable to use the plugin due to a similar error:
PhantomJS 1.9.7 (Mac OS X 0.0.0) ERROR TypeError: Attempting to change value of a readonly property. at /Users/you/Projects/myProject/test/unit/prototypes/jQueryAggregate.test.js:901

@speedskater
Copy link
Owner

Sorry for the Delay on the latest issues but i am currently in h

@speedskater
Copy link
Owner

on holidays and will return on the 23rd of november. I will then fix this bug and create a new beta.

@adamdicarlo
Copy link

@jorispz nice test case! I just stepped through that in Firefox and noticed something pretty interesting.

Here's some code within Redux:

    function assertReducerSanity(reducers) {
      Object.keys(reducers).forEach(function (key) {
        var reducer = reducers[key];
        var initialState = reducer(undefined, { type: _createStore.ActionTypes.INIT });

        if (typeof initialState === 'undefined') {
          throw new Error('Reducer "' + key + '" returned undefined during initialization. ' + 'If the state passed to the reducer is undefined, you must ' + 'explicitly return the initial state. The initial state may ' + 'not be undefined.');
        }

        var type = '@@redux/PROBE_UNKNOWN_ACTION_' + Math.random().toString(36).substring(7).split('').join('.');
        if (typeof reducer(undefined, { type: type }) === 'undefined') {
          throw new Error('Reducer "' + key + '" returned undefined when probed with a random type. ' + ('Don\'t try to handle ' + _createStore.ActionTypes.INIT + ' or other actions in "redux/*" ') + 'namespace. They are considered private. Instead, you must return the ' + 'current state for any unknown actions, unless it is undefined, ' + 'in which case you must return the initial state, regardless of the ' + 'action type. The initial state may not be undefined.');
        }
      });
    }

The __GetDependency__ key, for instance, is being enumerated by Object.keys! I would have though all the rewire stuff would be added as non-enumerable...?

@adamdicarlo
Copy link

Here's a snippet from babel-plugin-rewire itself:

                    t.blockStatement([
                        addNonEnumerableProperty(t, defaultExportVariableId, '__Rewire__', universalAccessors['__Rewire__']),
                        addNonEnumerableProperty(t, defaultExportVariableId, '__set__', universalAccessors['__Rewire__']),
                        addNonEnumerableProperty(t, defaultExportVariableId, '__ResetDependency__', universalAccessors['__ResetDependency__']),
                        addNonEnumerableProperty(t, defaultExportVariableId, '__GetDependency__', universalAccessors['__GetDependency__']),
                        addNonEnumerableProperty(t, defaultExportVariableId, '__get__', universalAccessors['__GetDependency__']),
                        addNonEnumerableProperty(t, defaultExportVariableId, '__RewireAPI__', universalAccessors['__RewireAPI__'])
                    ])

So I'm wondering if the Object.assign polyfill is what's messing up!

@adamdicarlo
Copy link

Nevermind about that. But I'm thinking potentially this has something to do with it:

    exports.hideNotification = _hideNotificationOrig;
    exports.__GetDependency__ = _GetDependency__;
    exports.__get__ = _GetDependency__;
    exports.__Rewire__ = _Rewire__;
    exports.__set__ = _Rewire__;
    exports.__ResetDependency__ = _ResetDependency__;
    exports.__RewireAPI__ = _RewireAPI__;
    exports['default'] = _RewireAPI__;

so problem from OP was maybe... import foo from './foo' rather than import { foo } from './foo' or something?

@speedskater
Copy link
Owner

As far as i have seen the problem in your PR is
import * as helloWorldReducers from './reducers.js';
The Problem is that i haven't found a solution how to prevent the wild card import to recognize the exports from rewire.
@sebmck do you have an idea how this could be achieved?

@speedskater
Copy link
Owner

@0x80 @kibin @jorispz @CrazyUmka @TheSavior @Dygerati @adamdicarlo Please all have a look at the latest beta 1.0.0-beta-4 . Could you please let me know if this solves your issues.
Regarding the case of wildcard imports used in combination with reducers as mentioned in the previous comment it is still not fixed. And imho it is not possible to fix this issue. Therefore does any of you object if we close this issue.

@jorispz
Copy link

jorispz commented Jan 7, 2016

@speedskater sorry to hear that it can't be fixed, but I'm fine with closing this issue. Thanks for the help!

@RB-Lab
Copy link

RB-Lab commented Jan 8, 2016

I can confirm that in 1.0.0-beta-4 problem seems disappeared.

@speedskater
Copy link
Owner

@jorispz maybe the wildcard export can be tackled, see #78. But it could take another three weeks and could break the rewire API.

@jorispz
Copy link

jorispz commented Jan 11, 2016

@speedskater don't worry about it - we refactored things around a bit to work around this issue, so don't fix it on my behalf (though feel free to do so regardless :-)

@speedskater
Copy link
Owner

By now we fixed wildcard imports as well. so we will close this bug. Keep in mind that having multiple wildcard exports in the same file is currently not supported by the plugin.

@antitoxic
Copy link

@speedskater

By now we fixed wildcard imports as well. so we will close this bug. Keep in mind that having multiple wildcard exports in the same file is currently not supported by the plugin.

How is that not in big bold letters in the README?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests