Recoil: Cannot set object including ArrayBufferView property

Created on 21 Sep 2020  路  2Comments  路  Source: facebookexperimental/Recoil

Recoil version is 0.0.13.

Steps To Reproduce

Run below code and click "Float64Array" or "Uint8Array" button, then error will be thrown.
https://codesandbox.io/s/condescending-gagarin-8r9gf?file=/src/App.js

const testState = atom({
  key: "test",
  default: null
});

const Inner = () => {
  const [test, setTest] = useRecoilState(testState);
  return (
    <div>
      value: {test && test.hoge.length}
      <button
        onClick={() => {
          setTest({ hoge: ["1111", "22222"] });
        }}
      >
        Array
      </button>
      <button
        onClick={() => {
          setTest({
            hoge: new Float64Array(new ArrayBuffer(64), 32, 2)
          });
        }}
      >
        Float64Array
      </button>
      <button
        onClick={() => {
          setTest({
            hoge: new Uint8Array(1)
          });
        }}
      >
        Uint8Array
      </button>
    </div>
  );
};

export default function App() {
  return (
    <RecoilRoot>
      <div className="App">
        <Inner />
      </div>
    </RecoilRoot>
  );
}

error detail is below.

Cannot freeze array buffer views with elements
deepFreezeValue
https://8r9gf.csb.app/node_modules/recoil/es/recoil.js:1675:10
Object.mySet [as set]
https://8r9gf.csb.app/node_modules/recoil/es/recoil.js:2143:9
setNodeValue
https://8r9gf.csb.app/node_modules/recoil/es/recoil.js:375:15
eval
https://8r9gf.csb.app/node_modules/recoil/es/recoil.js:580:30
Object.replaceState
https://8r9gf.csb.app/node_modules/recoil/es/recoil.js:1070:18
eval
https://8r9gf.csb.app/node_modules/recoil/es/recoil.js:578:60
Object.trace
https://8r9gf.csb.app/node_modules/recoil/es/recoil.js:515:10
setRecoilValue
https://8r9gf.csb.app/node_modules/recoil/es/recoil.js:578:18
eval
https://8r9gf.csb.app/node_modules/recoil/es/recoil.js:1360:5
onClick
...

Description

This error seems to relate to below line.
https://github.com/facebookexperimental/Recoil/blob/e018c3abfb68f559bf493ba244079fa73f89e79b/src/util/Recoil_deepFreezeValue.js#L65
Object.freeze cannot freeze ArrayBufferView(such as Float64Array, Uint8Array...etc).
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze
So, It may be necessary to add a process to check if it is ArrayBufferView value to the shouldNotBeFrozen function

Is there a better way to handle this?

Most helpful comment

Fixed in master. Not yet released, but you can use the build in the nightly branch.

All 2 comments

I guess it's fair to add a check for ArrayBufferView types in shouldNotBeFrozen. It is not possible to guarantee data preserving in the buffer, and I believe developers (assumably) know that they are using this technology at their own risk?

cc @drarmstr

Fixed in master. Not yet released, but you can use the build in the nightly branch.

Was this page helpful?
0 / 5 - 0 ratings