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

Switch internal directory representation to use maps #1169

Merged
merged 6 commits into from Sep 14, 2017

Conversation

Projects
None yet
4 participants
@50Wliu
Member

50Wliu commented Aug 23, 2017

Requirements

  • Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion.
  • All new code requires tests to ensure against regressions

Description of the Change

This PR switches the internal representations of directory entries to use Maps instead of Objects. While they are very similar, there is one big disadvantage to using Objects - Objects have internal and inherited properties/keys. Since setting object keys sets the key directly, this means that certain directory names can conflict and override the existing Object properties. A notable example of this is __proto__. Naming a directory __proto__ causes Tree View to override the base Object prototype, which leads to Very Bad Things(tm). Maps do not have this limitation.

Alternate Designs

Switching to Map was the first thing I considered, and it worked. Alternatives would be to refuse to load folders that contained __proto__ entries, to prevent __proto__ entries from being added to the Directory representation, or to use a different data structure. I chose Maps due to the reasons outlined above and because MDN states that Maps should be used if possible when there is the potential for unknown keys.

Benefits

The name of a directory should no longer render Atom unusable.

Possible Drawbacks

This changes the output of onDidRemoveEntries from an Object to a Map. I'm unaware if that's being used anywhere outside of Tree View (see below). In addition, the serialized expansion state has also changed from an Object to a Map, meaning that extra conversion code will need to be added for a smooth transition.

Applicable Issues

Fixes #1079

/cc @Alhadis to make sure that this doesn't affect file-icons (in my testing it didn't)
/cc @Daniel15

TODO:

  • Specs
  • Serialization conversion
  • Make sure this doesn't break any packages
@Alhadis

This comment has been minimized.

Show comment
Hide comment
@Alhadis

Alhadis Aug 23, 2017

Contributor

The same error probably occurs with files that're named __proto__, too. Did you check?

EDIT: Confirmed.

Contributor

Alhadis commented Aug 23, 2017

The same error probably occurs with files that're named __proto__, too. Did you check?

EDIT: Confirmed.

@50Wliu

This comment has been minimized.

Show comment
Hide comment
@50Wliu

50Wliu Aug 23, 2017

Member

Really? I'm pretty sure I tested out a __proto__ file and nothing broke.

Member

50Wliu commented Aug 23, 2017

Really? I'm pretty sure I tested out a __proto__ file and nothing broke.

Show outdated Hide outdated lib/directory-view.coffee Outdated
@Alhadis

This comment has been minimized.

Show comment
Hide comment
@Alhadis

Alhadis Aug 23, 2017

Contributor

Well, I created the __proto__ file from the tree-view's context-menu, and this happened as soon as I entered the filename:

Figure 1

After reloading the window, I encountered a different error:

Figure 2

Contributor

Alhadis commented Aug 23, 2017

Well, I created the __proto__ file from the tree-view's context-menu, and this happened as soon as I entered the filename:

Figure 1

After reloading the window, I encountered a different error:

Figure 2

@50Wliu

This comment has been minimized.

Show comment
Hide comment
@50Wliu

50Wliu Aug 23, 2017

Member

@Alhadis are you trying with my PR? The Directory class handles files to some extent as well, which is why I didn't have to change the File implementation.

Member

50Wliu commented Aug 23, 2017

@Alhadis are you trying with my PR? The Directory class handles files to some extent as well, which is why I didn't have to change the File implementation.

@Alhadis

This comment has been minimized.

Show comment
Hide comment
@Alhadis

Alhadis Aug 23, 2017

Contributor

Oh! Whoops, my bad. Yeah, your branch handles files as well. Never mind. 👼

Contributor

Alhadis commented Aug 23, 2017

Oh! Whoops, my bad. Yeah, your branch handles files as well. Never mind. 👼

@50Wliu

This comment has been minimized.

Show comment
Hide comment
@50Wliu

50Wliu Aug 23, 2017

Member

Just reminding myself which part of the serialization I need to work on:

Uncaught (in promise) TypeError: this.expansionState.entries.get is not a function
    at Directory.module.exports.Directory.getEntries (file:///C:/Users/user/Documents/GitHub/tree-view/lib/directory.coffee:196:52)
    at Directory.module.exports.Directory.reload (file:///C:/Users/user/Documents/GitHub/tree-view/lib/directory.coffee:231:5)
    at Directory.module.exports.Directory.expand (file:///C:/Users/user/Documents/GitHub/tree-view/lib/directory.coffee:269:6)
    at DirectoryView.module.exports.DirectoryView.expand (file:///C:/Users/user/Documents/GitHub/tree-view/lib/directory-view.coffee:133:18)
    at new DirectoryView (file:///C:/Users/user/Documents/GitHub/tree-view/lib/directory-view.coffee:62:6)
    at TreeView.<anonymous> (file:///C:/Users/user/Documents/GitHub/tree-view/lib/tree-view.coffee:296:14)
    at TreeView.module.exports.TreeView.updateRoots (file:///C:/Users/user/Documents/GitHub/tree-view/lib/tree-view.coffee:277:14)
    at new TreeView (file:///C:/Users/user/Documents/GitHub/tree-view/lib/tree-view.coffee:57:6)
    at TreeViewPackage.getTreeViewInstance (C:\Users\user\Documents\GitHub\tree-view\lib\tree-view-package.js:57:23)
    at Object.deserialize (C:\Users\user\AppData\Local\Atom x64\app-dev\resources\app\src\package.js:562:58)
    at DeserializerManager.deserialize (C:\Users\user\AppData\Local\Atom x64\app-dev\resources\app\src\deserializer-manager.js:95:35)
    at C:\Users\user\AppData\Local\Atom x64\app-dev\resources\app\src\pane.js:48:36
    at Array.map (native)
    at Function.module.exports.Pane.deserialize (C:\Users\user\AppData\Local\Atom x64\app-dev\resources\app\src\pane.js:47:27)
    at DeserializerManager.deserialize (C:\Users\user\AppData\Local\Atom x64\app-dev\resources\app\src\deserializer-manager.js:95:35)
    at PaneContainer.deserialize (C:\Users\user\AppData\Local\Atom x64\app-dev\resources\app\src\pane-container.js:58:44)
    at Dock.deserialize (C:\Users\user\AppData\Local\Atom x64\app-dev\resources\app\src\dock.js:378:30)
    at Workspace.deserialize (C:\Users\user\AppData\Local\Atom x64\app-dev\resources\app\src\workspace.js:416:40)
    at C:\Users\user\AppData\Local\Atom x64\app-dev\resources\app\src\atom-environment.js:1263:35
Member

50Wliu commented Aug 23, 2017

Just reminding myself which part of the serialization I need to work on:

Uncaught (in promise) TypeError: this.expansionState.entries.get is not a function
    at Directory.module.exports.Directory.getEntries (file:///C:/Users/user/Documents/GitHub/tree-view/lib/directory.coffee:196:52)
    at Directory.module.exports.Directory.reload (file:///C:/Users/user/Documents/GitHub/tree-view/lib/directory.coffee:231:5)
    at Directory.module.exports.Directory.expand (file:///C:/Users/user/Documents/GitHub/tree-view/lib/directory.coffee:269:6)
    at DirectoryView.module.exports.DirectoryView.expand (file:///C:/Users/user/Documents/GitHub/tree-view/lib/directory-view.coffee:133:18)
    at new DirectoryView (file:///C:/Users/user/Documents/GitHub/tree-view/lib/directory-view.coffee:62:6)
    at TreeView.<anonymous> (file:///C:/Users/user/Documents/GitHub/tree-view/lib/tree-view.coffee:296:14)
    at TreeView.module.exports.TreeView.updateRoots (file:///C:/Users/user/Documents/GitHub/tree-view/lib/tree-view.coffee:277:14)
    at new TreeView (file:///C:/Users/user/Documents/GitHub/tree-view/lib/tree-view.coffee:57:6)
    at TreeViewPackage.getTreeViewInstance (C:\Users\user\Documents\GitHub\tree-view\lib\tree-view-package.js:57:23)
    at Object.deserialize (C:\Users\user\AppData\Local\Atom x64\app-dev\resources\app\src\package.js:562:58)
    at DeserializerManager.deserialize (C:\Users\user\AppData\Local\Atom x64\app-dev\resources\app\src\deserializer-manager.js:95:35)
    at C:\Users\user\AppData\Local\Atom x64\app-dev\resources\app\src\pane.js:48:36
    at Array.map (native)
    at Function.module.exports.Pane.deserialize (C:\Users\user\AppData\Local\Atom x64\app-dev\resources\app\src\pane.js:47:27)
    at DeserializerManager.deserialize (C:\Users\user\AppData\Local\Atom x64\app-dev\resources\app\src\deserializer-manager.js:95:35)
    at PaneContainer.deserialize (C:\Users\user\AppData\Local\Atom x64\app-dev\resources\app\src\pane-container.js:58:44)
    at Dock.deserialize (C:\Users\user\AppData\Local\Atom x64\app-dev\resources\app\src\dock.js:378:30)
    at Workspace.deserialize (C:\Users\user\AppData\Local\Atom x64\app-dev\resources\app\src\workspace.js:416:40)
    at C:\Users\user\AppData\Local\Atom x64\app-dev\resources\app\src\atom-environment.js:1263:35
Show outdated Hide outdated lib/directory.coffee Outdated
@50Wliu

This comment has been minimized.

Show comment
Hide comment
@50Wliu

50Wliu Aug 28, 2017

Member

grep -r "onDidRemoveEntries" . found three packages with that text:

So it looks like only Tree View forks are using onDidRemoveEntries and therefore it should be safe to proceed with this implementation.

Member

50Wliu commented Aug 28, 2017

grep -r "onDidRemoveEntries" . found three packages with that text:

So it looks like only Tree View forks are using onDidRemoveEntries and therefore it should be safe to proceed with this implementation.

Alhadis added a commit to file-icons/atom that referenced this pull request Sep 1, 2017

@Alhadis

This comment has been minimized.

Show comment
Hide comment
@Alhadis

Alhadis Sep 1, 2017

Contributor

@50Wliu Just an FYI, there were indeed regressions with file-icons; specifically, directory icons were missing, and icons weren't responding to async changes in file/icon mappings. Not to worry though, I've got it all under control.

Contributor

Alhadis commented Sep 1, 2017

@50Wliu Just an FYI, there were indeed regressions with file-icons; specifically, directory icons were missing, and icons weren't responding to async changes in file/icon mappings. Not to worry though, I've got it all under control.

@as-cii

as-cii approved these changes Sep 6, 2017

I left one minor comment, but otherwise this looks good to me.

Nice work, @50Wliu! ⚡️

Show outdated Hide outdated lib/directory-view.coffee Outdated
@as-cii

This comment has been minimized.

Show comment
Hide comment
@as-cii

as-cii Sep 6, 2017

Member

One more question, related to @Alhadis' comment:

Just an FYI, there were indeed regressions with file-icons; specifically, directory icons were missing, and icons weren't responding to async changes in file/icon mappings. Not to worry though, I've got it all under control.

Are we worried at all about breaking other packages by shipping this pull-request?

Member

as-cii commented Sep 6, 2017

One more question, related to @Alhadis' comment:

Just an FYI, there were indeed regressions with file-icons; specifically, directory icons were missing, and icons weren't responding to async changes in file/icon mappings. Not to worry though, I've got it all under control.

Are we worried at all about breaking other packages by shipping this pull-request?

@Alhadis

This comment has been minimized.

Show comment
Hide comment
@Alhadis

Alhadis Sep 6, 2017

Contributor

Are we worried at all about breaking other packages by shipping this pull-request?

@as-cii I don't imagine there'd be a risk of runtime breakage. They were POJOs in the first place, which means any package using them would probably only be looping through their properties with a for..in loop.

However, this might lead to subtle regressions in packages which expect to find filenames in the form of enumerated key/value pairs (as file-icons had been).

Contributor

Alhadis commented Sep 6, 2017

Are we worried at all about breaking other packages by shipping this pull-request?

@as-cii I don't imagine there'd be a risk of runtime breakage. They were POJOs in the first place, which means any package using them would probably only be looping through their properties with a for..in loop.

However, this might lead to subtle regressions in packages which expect to find filenames in the form of enumerated key/value pairs (as file-icons had been).

@50Wliu

This comment has been minimized.

Show comment
Hide comment
@50Wliu

50Wliu Sep 6, 2017

Member

@as-cii could you expand on your concerns about the event order with the second option?

Member

50Wliu commented Sep 6, 2017

@as-cii could you expand on your concerns about the event order with the second option?

@50Wliu

This comment has been minimized.

Show comment
Hide comment
@50Wliu

50Wliu Sep 8, 2017

Member

@as-cii I have implemented the first option, just to be safe.

Member

50Wliu commented Sep 8, 2017

@as-cii I have implemented the first option, just to be safe.

@50Wliu 50Wliu merged commit d8b04dc into master Sep 14, 2017

1 of 2 checks passed

continuous-integration/travis-ci/pr The Travis CI build could not complete due to an error
Details
continuous-integration/appveyor/pr AppVeyor build succeeded
Details

@50Wliu 50Wliu deleted the wl-use-maps branch Sep 14, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment