Summary:
Ground work for allowing `font-variant`s. Currently allows switching between `tabular-nums` and `proportional-nums`. I will need guidance on how to test this, and a few pointers on code style (new to Objective C, and had to make one or two hacks).
Closes https://github.com/facebook/react-native/pull/9045
Reviewed By: majak
Differential Revision: D3664338
Pulled By: javache
fbshipit-source-id: 032f326c37ee6150348da2b33b6a3fc1988e8920
Summary:
This PR addresses issue #9265.
Negated the condition that checks if `_hostViews` exists so that `_hostViews` will be allocated only if it doesn't exist
Closes https://github.com/facebook/react-native/pull/9295
Differential Revision: D3686214
fbshipit-source-id: ec0caac99d231786eefad023f3f0ed44a79f687e
Summary:
When you call `-[RCTConvert UIFont:withFamily:...]` with a non-nil font object, we'll try to use the existing font object for system information. On iOS9+ which uses the San Francisco font, `[UIFont fontNamesForFamilyName:]` doesn't return anything useful, so we need to make sure that we detect this as a system font and use the appropriate methods. This issues is made worse by the fact that RCTTextView and friends recreate the font property for every attribute that is set (pretty horrible perf-wise).
This fixes https://github.com/facebook/react-native/issues/2140
Reviewed By: sahrens
Differential Revision: D3662751
fbshipit-source-id: c528e8945ed361a922c03f861d3c0b584658573b
Summary:
Consistently namespace all of css-layout's public C API with "CSS". The only function that needed to be renamed was isUndefined, which I renamed to CSSValueIsUndefined.
Fixes#210.
Closes https://github.com/facebook/css-layout/pull/211
Reviewed By: lucasr
Differential Revision: D3674922
Pulled By: emilsjolander
fbshipit-source-id: 1752f477bde45586db112fe2654d0404cc52e1d1
Summary:
1. Provide forceRTL function for developer to test RTL layout in LTR language bundle in I18nUtil and expose it in I18nManager.
2. Rename `allowRTL` and `setAllowRTL` functions
Reviewed By: fkgozali
Differential Revision: D3663693
fbshipit-source-id: 3db13a44c069ae73d1728c211306422db5dd8122
Summary:
When call `[RCTDevMenu invalidate]`, it will cancel updateTask. But in fact, after the `[updateTask cancel]`, the updateTask's completionHandler will call `checkForUpdates` again, so it will create a new updateTask.
Closes https://github.com/facebook/react-native/pull/6165
Differential Revision: D3669576
Pulled By: javache
fbshipit-source-id: 443924b7f4be1716797fc5690e90d962cf31b923
Summary:
Sometimes is handy to check if a React node is a descendant of another node or not. For instance, I want to check if the focused `TextInput` is descendant of an specific `ScrollView`:
```js
const currentlyFocusedField = TextInput.State.currentlyFocusedField()
UIManager.viewIsAncestorOf(
currentlyFocusedField,
this.getInnerViewNode(),
(isAncestor) => {
if (isAncestor) {
console.log('The focused field is a descendant of this ScrollView!')
}
}
)
```
This function uses the same strategy as the `measureLayout` method to check if one node is an ancestor of other node. As the `measureLayout` method, this is performed outside the main thread.
By now I've only implemented the iOS version and its tests, but if this function is going to be merged I'll implement the Android version too. I have objc experience but no Java or Android, so I prefer to validate this functionality before jumping into developing the Android part.
Closes https://github.com/facebook/react-native/pull/7876
Differential Revision: D3662045
Pulled By: javache
fbshipit-source-id: b9668e8ea94fd01db76651f16243926cf9c2566f
Summary: The new CSSLayout have a wrong calculate for the getRelativePosition. So use the getLeadingPosition will get 0 instead of return undefined. Fix it with using isLeadingPosDefined.
Reviewed By: fkgozali
Differential Revision: D3640799
fbshipit-source-id: 50d3bd2ea4c0d8bf96ba34297425ba269b0535cd
Summary:
The make current RCTShadowView support RTL layout.
Two changes I made:
1 Change all left/right to start/end for margin, padding, boarder and position
2 Change the paddingAsInsets to support RTL
Reviewed By: majak
Differential Revision: D3548002
fbshipit-source-id: 15cc5228d2d28d0e12a7147daf57967e5b87ee63
Summary:
The current CSSLayout can't support RTL because wrong calculation for absolute position.
This change is mainly to fix the issue: https://github.com/facebook/css-layout/issues/197
Three main problems I fixed:
1. Calculate the position in the same way as margin, boarder, and padding. So that to fix the absolute problem.
2. Fix one wrong calculation for leading value when we only know the trailing value. It was hard code for the LTR situation. Now I changed it to depends on the main Axis.
3. Expose getter and setter function for RN to read layout direction and start/end position value.
Reviewed By: fkgozali
Differential Revision: D3616949
fbshipit-source-id: ae7a47cc0a5d02b42b95f87232be51ab144056d9
Summary: Mirrors Android's support for multiple sources for Image, allowing us to fetch new images as the size of the view changes.
Reviewed By: mmmulani
Differential Revision: D3615134
fbshipit-source-id: 3d0bf2b75f63a4379e0e49f2dab9aea351b31d5f
Summary:
This uses `[UIImage imageNamed:]` to load local assets that are bundled using `require('../image/path.png')` and makes sure it is done synchronously on the main queue to prevent images from flickering. This improves user experience a lot when using large local images and prevents icon flickers to match the behaviour of most native apps.
This adds to methods to the ImageLoader protocol, one to tell if the image loader must be executed on the url cache queue and one to tell if the result of the image loader should be cached. I then use these to make the LocalImageLoader bypass the url cache queue and avoid caching images twice.
Note that this doesn't affect debug builds since images are loaded from the packager.
I'm not sure if we want to still support async loading of local images as I'm not sure how much of a perf difference this will make. Maybe someone at fb can benchmark this see how it affects your apps but there wasn't a noticeable one in mine. Also I only enabled this for loading png and jpg im
Closes https://github.com/facebook/react-native/pull/8102
Reviewed By: bnham
Differential Revision: D3433647
Pulled By: javache
fbshipit-source-id: 37bd6aff20c0465c163db3cdbcaeaedff55f7b1f
Summary: RCTShadowText currently overrides a couple methods from RCTShadowView to reset the count of the cssNode children to 0. This diff instead moves that logic into RCTShadowView behind a configurable flag making it easier to reason about.
Reviewed By: javache
Differential Revision: D3586434
fbshipit-source-id: 4389a8119dc49e3fc4357174c87c0c69287ae385
Summary: fillCSSNode was only ever used in RCTShadowView to set the child count which is already performed in insert/remove subview calls and in RCTShadowText is was used to set the measure function which can be done in the initializer instead.
Reviewed By: majak, javache
Differential Revision: D3586418
fbshipit-source-id: de2155daf0f1702c8977bf23183a3b6a650d016b
Summary: Add some additional perf markers, and remove the usage of RCTProfileBlock as it completely breaks debugging / stepping in those blocks.
Reviewed By: majak
Differential Revision: D3579900
fbshipit-source-id: 8846dfc39b2448daa3669d5e1e8efb9096f183c5
Summary:
As per javache comments in #8734.
Also removes now useless feature detection check.
**Test plan**
Tested that rIC still works in UIExplorer example.
Closes https://github.com/facebook/react-native/pull/8795
Differential Revision: D3572566
Pulled By: javache
fbshipit-source-id: 261d13d8b03898313f8b4184d634c70f81a61b62
Summary: Instead of the somewhat odd concept of a "packager running predicate", just expose a class method for generating a JS bundle URL given a host, root, and options. This can be used by consumers that need custom behavior.
Reviewed By: javache
Differential Revision: D3564185
fbshipit-source-id: b1a7e66a2dada6a9eefe783b12b03fca7a330be3
Summary:
iOS follow up to #8569. This currently depends on the Android PR since it contains the JS implementation, only review the last commit. Just putting this out here for visibility, don't merge this before the Android PR.
**Test plan**
Tested by running a background task that burns all remaining idle time (see UIExplorer example).
Tested that native only calls into JS when there are pending idle callbacks.
Tested that timers are executed before idle callback.
Closes https://github.com/facebook/react-native/pull/8734
Differential Revision: D3560818
fbshipit-source-id: a28d3092377a7fd4331647148d40fe69e4198c7e
Summary: The docs for this new method explain what it does.
Differential Revision: D3556890
fbshipit-source-id: b075e750cdd1e7354e0a26c03b3fd74cca52aeb7
Summary:
- Avoid using `+initialize`, use dispatch_once instead; it should be equivalent but more performant.
- Don't even let the `isPackagerRunning:` and `guessPackagerHost` methods exist unless `RCT_DEV` is on; they didn't do anything interesting when it is off.
Reviewed By: javache
Differential Revision: D3556645
fbshipit-source-id: 7dcdb4ae27f6625010e15846d757269f6f04155c
Summary: Include the actual scheme instead of "non-file".
Reviewed By: javache
Differential Revision: D3555812
fbshipit-source-id: 3ae0490f2d8fae01a551ba2877789dc15818fc50
Summary:
WebView component detect phone numbers in html as URL links by default. But sometimes we don't want this behavior.
This PR add dataDetectorTypes as a prop of WebView, so one can specify value of this prop as one or more of phoneNumber/link/address/calendarEvent/none/all
This prop maps to UIWebView.dataDetectorTypes
Closes https://github.com/facebook/react-native/pull/8743
Differential Revision: D3556440
fbshipit-source-id: 55f01d2cdd785381f261a9dc931aa9311f0ad1d4
Summary: No need to specify duplicative information.
Reviewed By: javache
Differential Revision: D3550805
fbshipit-source-id: b5abc3f1c74e26b4d4641c29fedba189cc46406e
Summary:
Attempt to fix#7919.
Currently, if the app is launched into the background and you read `AppState.currentState` too soon, you will see the value `'active'` instead of `'background'`. This is because the default value of `AppState.currentState` is hardcoded to be `'active'` and it is initialized with the actual value asynchronously.
This attempts to fix the bug by having the `RCTAppState` module provide the initial state as a module constant.
As noted in #7919, it looks like this fix was already tried and reverted with 0fb3d8de83. zjj010104, hedgerwang, nicklockwood -- can you explain why? I would very much like to get this bug fixed. Nobody has followed up on the issue I filed so I decided to just go ahead and make a PR with my best guess at a fix.
**Test plan (required)**
Built a small app as described in the repro steps for #7919 and verified that, when the app is launched into the background, `init currentState: background` is printed. Also verified that `i
Closes https://github.com/facebook/react-native/pull/8058
Differential Revision: D3554619
fbshipit-source-id: 5d950b85e335765552bbd3cf6ed91534062e35a1
Summary: This prevents the `isUnbundle` check to read beyond the end of an `NSData` instance by using `getBytes:length:` instead of accessing the underlying buffer directly.
Reviewed By: javache
Differential Revision: D3548874
fbshipit-source-id: 7c93c66cc6abb4a2a321888ab394212f4d14a03e
Summary: The loader should be a utility that stands alone. The bridge uses the loader, not the other way around.
Reviewed By: bnham
Differential Revision: D3546157
fbshipit-source-id: 91016afb629df1f8c83c8fca6f42649be0b046b0
Summary:
This diff exposes a new experimental method `[RCTJavaScriptLoader +attemptSynchronousLoadOfBundleAtURL:sourceLength:error:]`. It may be used if you know that a specific call site must load its JavaScript synchronously, or else fail entirely.
This new API will succeed for file URLs that point to a RAM bundle. It will fail for non-RAM-bundle files and for HTTP URLs.
This also cleans up the error domain and codes for this class. This should be the only externally visible change from this diff if you don't use the new API: the codes and domains you receive from the API may change slightly. They were pretty sloppy and undocumented before, so I think this change is for the better.
Reviewed By: bnham
Differential Revision: D3545956
fbshipit-source-id: 30e65f4e8330d2d68f3f50ade077fdc1db4a435e
Summary:
The `initWithJSContextProvider:` API created a `RCTJSCExecutor` with a thread/context that already exists, but it did not solve the problem of loading an actual application script; the `executeApplicationScript:` API is also asynchronous.
Create a new merged API that allows you to pass in a pre-created thread/context pair and immediately receive an `RCTJSCExector` that has already executed a specified application script.
This also removes the `underlyingJSContext` API entirely, in favor of passing it back in a byref variable in the new API. This minimizes the surface area for API abuse.
Reviewed By: bnham
Differential Revision: D3545349
fbshipit-source-id: 1c564f44d2a5379b5e6f75640079a28fd7169f67
Summary:
Instead of two separate dispatches to the JavaScript thread, only do one. Avoid the strongSelf dance entirely.
This refactor does mean that the cost of registering the nativeRequire hook on the context is not measured by the `RCTPLRAMBundleLoad` tag. However it should be almost zero-cost to construct and set a single block, so I'm OK with that change.
Reviewed By: bnham
Differential Revision: D3542940
fbshipit-source-id: d6bd26e478d0d33b56f8116d7efe6aac80c91711
Summary: We deprecated it a while back and nobody is using it internally.
Reviewed By: majak
Differential Revision: D3542602
fbshipit-source-id: dfe11a47b21d2f8a7c946c902f0ea427615ffc31
Summary: This makes the state it uses more explicit. It also makes a bug with performance measurement obvious: if we early return to error, we never mark stop for `RCTPLRAMStartupCodeSize`.
Reviewed By: javache
Differential Revision: D3542751
fbshipit-source-id: e6c1e3f3a76098ca37b8078f6e9abc805ad2d9da
Summary:
By default we run the the JS display link, even if there are no modules listening. Given that most listeners will be lazily constructed, let's make it paused by default.
Since RCTTiming almost never unpauses due to some long-lived timers, implement a sleep timer that pauses the displaylink but uses an NSTimer to wake up in time.
Reviewed By: mhorowitz
Differential Revision: D3235044
fbshipit-source-id: 4a340fea552ada1bd8bc0d83b596a7df6f992387
Summary:
Currently React Native codebase treats JS stack traces as array of dictionaries.
This diff switches the Red Box to use new `RCTJSStackFrame` for internal data representation, while keeping the exposed API unchanged. The next step would be to replace the rest of manual parsing and usage of dictionaries.
The new class has ability to parse the stack from raw strings or dictionaries.
Depends on D3429031
Reviewed By: javache
Differential Revision: D3473199
fbshipit-source-id: 90d2a4f5e8e054b75c99905f35c2ee54927bb311
Summary: This can be used to create a JavaScript thread and `JSContext` in advance, then supply them to the `RCTJSCExecutor` at creation time later.
Reviewed By: javache
Differential Revision: D3534553
fbshipit-source-id: 99ccf711928cd12e84c9fbe142c6d19a7af55d07
Summary: This was left over from a previous change.
Reviewed By: javache
Differential Revision: D3534376
fbshipit-source-id: 6932364d1c32d8fbdf56c642893f9ea5e6dc1fee
Summary:
https://github.com/facebook/css-layout/pull/199
- Nodes were measured with the assumption of being text nodes (height depends on width) when determining flex basis. This is not always true. Even when we are just interested in the main axis (flex basis) we need to correctly constrain the cross axis.
- Some tests were wrong. Measuring texts.big and expecting it to have textSizes.smallHeight which doesn't make a lot of sense.
Reviewed By: vjeux
Differential Revision: D3510163
fbshipit-source-id: ee53b548dd078005fdd153d279e4c7fef3dd02d0
Summary:
In practice, it *MUST* be the call to `self.context` within `setUp` that triggers the creation of the context:
- It can't come before that point because `_jscWrapper` has not been set up yet
- It can't come after that point since `self.context` would create the context there.
Just move the creation to be inline, enforced by assert. This makes it easier to reason about where the context is created, and easier to change how it is created later.
Reviewed By: javache
Differential Revision: D3529843
fbshipit-source-id: 8ed5a9861ebefd4b9e0f7155db8587dcf0442b7a
Summary: There's no reason for this; setUp is once-and-done. Probably just trying to ignore the incorrect clang warning.
Reviewed By: javache
Differential Revision: D3528494
fbshipit-source-id: e4f986df8d097e4720dfd4a51e7fb6c9c9b5108f
Summary:
https://github.com/facebook/css-layout/pull/200
Make use of max dimension styles to allow root to be measured with AT_MOST measure mode
Reviewed By: IanChilds
Differential Revision: D3513505
fbshipit-source-id: 169f49717e896eb6270b52fb7115ce005aa0e3a8
Summary: I think this obscures more than it helps. Remove it.
Reviewed By: javache
Differential Revision: D3528677
fbshipit-source-id: d90a636a6e34b66563d9a02e255c6ebc4cee1294
Summary:
Ideally, native hooks should not require any sort of reference to self. Pull all those that fulfill this criteria into a class method (to make it impossible to accidentally capture self).
Future diffs will pull more and more hooks into this category.
Reviewed By: javache
Differential Revision: D3528558
fbshipit-source-id: 270c5bec53674a91ec2129d55e5cad59440a51da
Summary: It's just a simple helper. It's actually more readable and performant when inlined.
Reviewed By: javache
Differential Revision: D3528540
fbshipit-source-id: 8086770f7fd88b40623dc943c715deb4f9fd9262
Summary: This leaves no optional methods on `RCTJavaScriptExecutor`, which is certainly a good thing.
Reviewed By: majak
Differential Revision: D3518915
fbshipit-source-id: e606b9076c3299f81a225a181ea244148a1832cb
Summary: It's not widely used, and you can do something equivalent anyway by using existing public API.
Reviewed By: javache
Differential Revision: D3518896
fbshipit-source-id: 6995a5d840aecfff4ffd78ac43f3f592a4f47f91
Summary: Reading four bytes is not slow. Don't bother dispatching for that.
Reviewed By: javache
Differential Revision: D3518405
fbshipit-source-id: 910079cec2a1f624dd71760438765bd035055229
Summary: No need to have these way at the top; they're not used until later.
Reviewed By: majak
Differential Revision: D3518364
fbshipit-source-id: 3e7461665e90dea5c6d323d45b1ffb11fb610b09
Summary: No need to keep it open; it just makes it harder to reason about error handling.
Reviewed By: majak
Differential Revision: D3518200
fbshipit-source-id: dc1af6eb0f75de7e9f73513ed1dd522048f76670
Summary:
Delete the bridge functions(isRTL, allowRTL()) in internal module and move to OSS.
Create bridge for RCTI18nUtil
Reviewed By: fkgozali
Differential Revision: D3519224
fbshipit-source-id: 3853edcfcc78777d957874448117de72ae0700b5
Summary:
Thanks for submitting a pull request! Please provide enough information so that others can review your pull request:
(You can skip this if you're fixing a typo or adding an app to the Showcase.)
Explain the **motivation** for making this change. What existing problem does the pull request solve?
Prefer **small pull requests**. These are much easier to review and more likely to get merged. Make sure the PR does only one thing, otherwise please split it.
**Test plan (required)**
Demonstrate the code is solid. Example: The exact commands you ran and their output, screenshots / videos if the pull request changes UI.
Make sure tests pass on both Travis and Circle CI.
**Code formatting**
Look around. Match the style of the rest of the codebase. See also the simple [style guide](https://github.com/facebook/react-native/blob/master/CONTRIBUTING.md#style-guide).
For more info, see the ["Pull Requests" section of our "Contributing" guidelines](https://github.com/facebook/react-native/blob/mas
Closes https://github.com/facebook/react-native/pull/7535
Differential Revision: D3509757
fbshipit-source-id: 70ff6c9c137c766ccb1173921f08571f48cb4f0b
Summary:
I used the reproducible steps as described in origin bug ticket #7987 as test plan.
This has the same contents as PR #8130 but then against master per janicduplessis request.
Closes https://github.com/facebook/react-native/pull/8134
Differential Revision: D3491126
fbshipit-source-id: a22669dc998f82b36fbe31d882d0a29f0912e2ee
Summary: Rename the forceRTL to allowRTL so that make it much clear to read. And change a typo.
Reviewed By: fkgozali
Differential Revision: D3489235
fbshipit-source-id: b9803dfbcda2f764b7e752c9810cfc7a0b9fe39b
Summary: Provide function that could read the language currently used in the app, so the isRTL is using the app current using language to set isRTL.
Reviewed By: fkgozali
Differential Revision: D3480654
fbshipit-source-id: dea3ef4769296f594f7f32da2961b4fec1b99a7a
Summary: Create isDeviceLanguageRTL function to connect the OS language with isRTL. Now even if a new app could support RTL language, without setting forceRTL at JS side it won't directly change into RTL layout.
Reviewed By: fkgozali
Differential Revision: D3473109
fbshipit-source-id: ac1410c910e980d44750bb88cad7615febb9e076
Summary:
88c6e7a22b / D3446871 broke the OSS version of React where React.xcodeproj isn't autogenerated.
**Test plan:** UIExplorer example works again.
Closes https://github.com/facebook/react-native/pull/8288
Differential Revision: D3466246
Pulled By: javache
fbshipit-source-id: 1240b755b0df54ddfde016d0122640293e50caeb
Summary: This diff build the connection between the native code and js code so that the js could get IsRTL value and us ForceRTL function.
Reviewed By: fkgozali
Differential Revision: D3447013
fbshipit-source-id: 9f6c7f71cef0add7bd5beb0ba2b1543f0cabc2b3
Summary: Create a module for React Native to get IsRTL information and set ForceRTL function.
Reviewed By: fkgozali
Differential Revision: D3446871
fbshipit-source-id: 736edf138a89d222818071370ac49dc54bda63b7
Summary:
Issue we were seeing: scrollview would clip its cells when it was resized to 0 height and moved offscreen, but it wouldn't add it back when it was resized and moved back
Why this was happening: scrollview wouldn't rerun its un/clipping logic after the first run unless 1/it has 0x0 frame or 2/it has been scrolled. Neither was happening here.
Fix: run the un/clipping logic when scrollview's frame has been changed since the last clipping.
Reviewed By: javache
Differential Revision: D3436996
fbshipit-source-id: 1a8cfeb72b425fcc80815d30743fa308b9c75ab6
Summary:
We already do this on Android, and it allows uw to avoid doing this global object lookup for every call. Since there's only a couple of global functions we ever call, we should consider caching all of them in the new bridge.
I didn't ValueProtect/ValueUnprotect since these are already globals, and those methods are not exposed on the JSC wrapper.
Reviewed By: mhorowitz
Differential Revision: D3411487
fbshipit-source-id: 7feaf8803665b77d649e84edad875d31c5acee4b
Summary:
Implemented automatic IP detection for iOS, based on #6345 and #6362.
As the previous pull requests did, this works by writing the IP address of the host to a file.
Closes https://github.com/facebook/react-native/pull/8091
Differential Revision: D3427657
Pulled By: javache
fbshipit-source-id: 3f534c9b32c4d6fb9615fc2e2c3c3aef421454c5
Summary: Expose the ability to provide extra information to Systrace events from JS. This is specifically useful for instrumenting generic recursive method that are defined completely through their params.
Reviewed By: tadeuzagallo
Differential Revision: D3423595
fbshipit-source-id: 7f2dedf02bf901401a6b391b85b1a0bb6782349c
Summary:
Fix a bug that happens when views are added and removed in the same manageChildren block with a delete animation. What happens is that the inserted view is not inserted at the proper index if the deleted view index is smaller than the inserted one. This is because the view is not immediately removed from the subviews array so we need to offset the insert index for each view that is going to be deleted with an animation and is before the inserted view.
To do this I separated `_removeChildren` into 2 different functions, one for animated delete and one for normal delete. The animated one returns an array of `RCTComponent` that are going to be animated. We can then use this array to offset the insert index.
**Test plan (required)**
Tested that this fixed the bug in an app where I noticed it, also tested the UIExplorer example to make sure LayoutAnimations still worked properly.
Closes https://github.com/facebook/react-native/pull/7942
Differential Revision: D3417194
Pulled By: bestander
fbshipit-source-id: 9145a783e520c6718dd023a1e006646acb09cb7c
Summary:
Fix a bug that happens when views are added and removed in the same manageChildren block with a delete animation. What happens is that the inserted view is not inserted at the proper index if the deleted view index is smaller than the inserted one. This is because the view is not immediately removed from the subviews array so we need to offset the insert index for each view that is going to be deleted with an animation and is before the inserted view.
To do this I separated `_removeChildren` into 2 different functions, one for animated delete and one for normal delete. The animated one returns an array of `RCTComponent` that are going to be animated. We can then use this array to offset the insert index.
**Test plan (required)**
Tested that this fixed the bug in an app where I noticed it, also tested the UIExplorer example to make sure LayoutAnimations still worked properly.
Closes https://github.com/facebook/react-native/pull/7942
Differential Revision: D3417194
Pulled By: nicklockwood
fbshipit-source-id: 790f4ac15a8552323b359e6466cecfa80418c63c
Summary: Converted the zIndex property on iOS to NSInteger instead of double. This is consistent with the CSS spec, and helps to simplify the Android implementation.
Reviewed By: javache
Differential Revision: D3411491
fbshipit-source-id: 902ebc29aac39a65f7e8707a28607655f9f5052c