-
Notifications
You must be signed in to change notification settings - Fork 18
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
Simple object check #17
Comments
hi @Gongreg ,
If you're sure the object structure is all immutable, then you're good to go like this. But be careful, if the object structure has some non-plain objects in it, they might get unexpectedly treated as immutable. Like, class Foo {
bar = 1;
}
const initState = { foo: new Foo(), a: { b: 1 } };
const state = create(
initState,
(draft) => {
draft.foo.bar = 2;
},
{
mark: () => 'immutable',
}
);
expect(state.foo).toBeInstanceOf(Foo);
expect(state.foo).not.toBe(initState.foo); Any objects in
Typically, when using the For example, class Foo {
bar = 1;
}
const initState = { foo: new Foo(), a: { b: 1 }, time: new Date() };
const [state, patches] = create(
initState,
(draft) => {
draft.foo.bar = 2;
draft.time.setDate(2);
},
{
enableAutoFreeze: true,
enablePatches: true,
mark: (value) => {
if (value instanceof Foo) return 'immutable';
},
}
);
expect(state.foo).toBeInstanceOf(Foo);
expect(state.foo).not.toBe(initState.foo);
expect(state.time).toBe(initState.time); initState.time is mutable, but the patches don't include its update. So, we can't get an equivalent object structure by applying those patches. But if you use I've already updated it in the docs.
You can use const isSimpleObject = (value) => {
const prototype = Object.getPrototypeOf(value);
if (prototype === null) {
return true;
}
const constructor =
Object.hasOwnProperty.call(prototype, 'constructor') &&
prototype.constructor;
return (
typeof constructor === 'function' &&
Function.toString.call(constructor) ===
Object.prototype.constructor.toString()
);
};
const initialState = iframe.someFunction();
const state = create(initialState, callback, {
mark: (value) => {
if (isSimpleObject(value)) {
return 'immutable';
}
},
});
I'm thinking about adding some potentially useful |
I've released Mutative v0.7.3, which supports marking simple objects. For example, import { create, markSimpleObject } from 'mutative';
const baseState = {
foo: {
bar: 'str',
},
simpleObject: Object.create(null),
};
const state = create(
baseState,
(draft) => {
draft.foo.bar = 'new str';
draft.simpleObject.a = 'a';
},
{
mark: markSimpleObject,
}
);
expect(state.simpleObject).not.toBe(baseState.simpleObject); |
In this conversation I found that NodeJS code creates simple objects everywhere (in the form of With that in mind, and not knowing what type of data a developer might stick into one of my drafted states, wouldn't it be safer to always check if Also, am I protected against this if |
hi @waynebloss , The main issue is that protecting the Object prototype is very costly, and it may vary depending on the browsers, requiring unnecessary overhead. Moreover, prototype chain pollution is not common. Specifically, there are multiple ways to access the prototype chain, such as: Therefore, I think it is not very necessary for us to do this, don't you think so? |
@unadlib I was not trying to protect against object prototype pollution - I was surprised when I observed that objects created with |
I tried it out and I see that e.g. > var baseState = { a: {}, b: Object.create(null) };
undefined
> var [draft, finalize] = create(baseState, { enablePatches: true, strict: true });
undefined
> draft.a.name = "a";
'a'
> draft.b.name = "b";
Uncaught:
Error: Strict mode: Mutable data cannot be accessed directly, please use 'unsafe(callback)' wrap.
at checkReadable
at Object.get |
Hello.
First of all thank you for the library, it works really great!
I've just bumped into one issue. In our setup we have iframe & parent window running on same domain and interacting with one another.
One of those interactions is:
Due to this, even though the returned object is "simple", the
Object.getPrototypeOf(value) === Object.prototype
check fails.I can overcome this by using mark functionality:
This brings a couple of questions:
mark: () => "immutable",
? Will this lead to some side effects? I haven't digged too deep into the source code yet, but couldn't find info in the docs.mark
docs, it says that (AutoFreeze and Patches should both be disabled). Is that really the case? I've tried to use them withmark
and it looked like it works fine.The text was updated successfully, but these errors were encountered: