-
Notifications
You must be signed in to change notification settings - Fork 187
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow specifying styles as
Map
s to guarantee ordering
Summary: Key ordering in objects can be different in different environments. Sometimes, this causes problems, like where styles generated on the server are not in the same order as the same styles generated on the client. This manifests in problems such as #199 This change lets users manually fix instances where the ordering of elements changes by specifying their styles in an ES6 `Map`, which has defined value ordering. In order to accomplish this, an `OrderedElements` class was created, which is sorta like a `Map` but can only store string keys and lacks most of the features. Internally, `Map`s and objects are converted into this and then these are merged together to preserve the ordering. Fixes #199 Test Plan: - `npm test` @lencioni @ljharb
- Loading branch information
Showing
8 changed files
with
463 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
/* @flow */ | ||
/* global Map */ | ||
|
||
export default class OrderedElements { | ||
/* :: | ||
elements: {[string]: any}; | ||
keyOrder: string[]; | ||
static fromObject: ({[string]: any}) => OrderedElements; | ||
static fromMap: (Map<string,any>) => OrderedElements; | ||
static from: (Map<string,any> | {[string]: any} | OrderedElements) => | ||
OrderedElements; | ||
*/ | ||
|
||
constructor( | ||
elements /* : {[string]: any} */ = {}, | ||
keyOrder /* : string[] */ = [] | ||
) { | ||
this.elements = elements; | ||
this.keyOrder = keyOrder; | ||
} | ||
|
||
forEach(callback /* : (string, any) => void */) { | ||
for (let i = 0; i < this.keyOrder.length; i++) { | ||
callback(this.keyOrder[i], this.elements[this.keyOrder[i]]); | ||
} | ||
} | ||
|
||
map(callback /* : (string, any) => any */) /* : OrderedElements */ { | ||
const results = new OrderedElements(); | ||
for (let i = 0; i < this.keyOrder.length; i++) { | ||
results.set( | ||
this.keyOrder[i], | ||
callback(this.keyOrder[i], this.elements[this.keyOrder[i]]) | ||
); | ||
} | ||
return results; | ||
} | ||
|
||
set(key /* : string */, value /* : any */) { | ||
if (!this.elements.hasOwnProperty(key)) { | ||
this.keyOrder.push(key); | ||
} | ||
this.elements[key] = value; | ||
} | ||
|
||
get(key /* : string */) /* : any */ { | ||
return this.elements[key]; | ||
} | ||
|
||
has(key /* : string */) /* : boolean */ { | ||
return this.elements.hasOwnProperty(key); | ||
} | ||
} | ||
|
||
OrderedElements.fromObject = (obj) => { | ||
return new OrderedElements(obj, Object.keys(obj)); | ||
}; | ||
|
||
OrderedElements.fromMap = (map) => { | ||
const ret = new OrderedElements(); | ||
map.forEach((val, key) => { | ||
ret.set(key, val); | ||
}); | ||
return ret; | ||
}; | ||
|
||
OrderedElements.from = (obj) => { | ||
if (obj instanceof OrderedElements) { | ||
// NOTE(emily): This makes a shallow copy of the previous elements, so | ||
// if the elements are deeply modified it will affect all copies. | ||
return new OrderedElements({...obj.elements}, obj.keyOrder.slice()); | ||
} else if ( | ||
// For some reason, flow complains about a plain | ||
// `typeof Map !== "undefined"` check. Casting `Map` to `any` solves | ||
// the problem. | ||
typeof /*::(*/ Map /*: any)*/ !== "undefined" && | ||
obj instanceof Map | ||
) { | ||
return OrderedElements.fromMap(obj); | ||
} else { | ||
return OrderedElements.fromObject(obj); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.