axilleasiv / vscode-javascript-repl-docs

JavaScript REPL is a javascript playground for Visual Studio Code with live feedback as you type, besides your code
69 stars 5 forks source link

Proxying objects?: REPL doesn't play nice with Immer #18

Open kredati opened 4 years ago

kredati commented 4 years ago

First: thank you for a brilliant extension. I use this all the time, and it makes my life much, much happier.

The issue is this: I've started using Immer to achieve immutability in a codebase. Immer checks that the objects it receives are "immerable," usually meaning that they are "plain" objects (i.e., object literals). The following work in VSCode running the REPL:

import produce from 'immer';

produce([1, 2, 3], draft => { draft.push(4); }); //=> [1, 2, 3, 4]

produce(Object.create(null), draft => { draft.foo = 42; }); //=> [Object: null prototype] { foo: 42 }

However, the following should work. And it does work just fine in Node, and in the command line Node REPL (14.6.0):

produce({}, draft => { draft.foo = 42; }); //=> { foo: 42 }

Using the JavaScript REPL, however, I get the following error when I run that code:

[Immer] produce can only be called on things that are draftable: plain objects, arrays, Map, Set or classes that are marked with '[immerable]: true'. Got '[object Object]'

Of course, I just passed in an empty object literal, a plain object.

I suspect the REPL is modifying the object literal in a way that is triggering this error because it fails some test in Immer. (Immer's source is not very easily navigable; I can dig into the code if you'd like.) Of course, ({}).constructor === Object.

Is the REPL proxying object literals? (But not objects with null prototypes?) Is there something else going on?

And again—thanks for a really, really useful plugin. I've been using it intensively for months and am really delighted by it.

axilleasiv commented 4 years ago

Hi, @kredati thank you so much for your feedback, I really appreciate it.

I have reproduced this successfully, so it is a bug!

The JavaScript REPL does not modify the object literal, so I checked the source code of Immer and I am thinking that for some reason the extension maybe fails on this check https://github.com/immerjs/immer/blob/467ea5d3b5d062c084ce6d875f8d77e21f26965c/src/utils/common.ts#L40

Until this bug will be fixed, a solution to your issue is to change the "JavaScript-repl: Context" option in vscode preferences-settings https://github.com/axilleasiv/vscode-javascript-repl-docs/wiki/Configuration#context and use 'Node' instead of the default 'VM'. I have tested your example and it works properly.

Thanks again for you feedback and feel free to post again if you have any issue or question.

kredati commented 4 years ago

Thanks for the quick reply. The workaround works on my end. And thanks again for the extension!