Summary:We found that moving the preloaded modules to the startup section of the RAM Bundle improves TTI quite a bit by saving lots of through the bridge calls and injecting multiple modules at once on JSC. However, doing this on a non hacky way required a lot of work. The main changes this diff does are:
- Add to `BundleBase` additional bundling options. This options are fetched based on the entry file we're building by invoking a module that exports a function (`getBundleOptionsModulePath`).
- Implement `BundleOptions` module to include the `numPreloadedModules` attribute as a bundle additional option. This value is computed by getting the dependencies the entry file has and looking for the first module that exports a module we don't want to preload. The `numPreloadedModules` attribute is then used to decide where to splice the array of modules.
- Additional kung fu to make sure sourcemaps work for both preloaded and non preloaded modules.
Reviewed By: davidaurelio
Differential Revision: D3046534
fb-gh-sync-id: 80b676222ca3bb8b9eecc912a7963be94d3dee1a
shipit-source-id: 80b676222ca3bb8b9eecc912a7963be94d3dee1a
Summary:It was hard to understand which parts of the shadowview API are designed to be called only on the root view, and which were applicable to any view.
This diff extracts rootview-specific logic out into a new RCTRootShadowView class.
Reviewed By: majak
Differential Revision: D3063905
fb-gh-sync-id: ef890cddfd7625fbd4bf5454314b441acdb03ac8
shipit-source-id: ef890cddfd7625fbd4bf5454314b441acdb03ac8
Summary: For RAM bundling we don't want to hold the entire bundle in memory as that approach doesn't scale. Instead we want to seek and read individual sections as they're required. This rev does that by detecting the type of bundle we're dealing with by reading the first 4 bytes of it. If we're dealing with a RAM Bundle we bail loading.
Reviewed By: javache
Differential Revision: D3026205
fb-gh-sync-id: dc4c745d6f00aa7241203899e5ba136915efa6fe
shipit-source-id: dc4c745d6f00aa7241203899e5ba136915efa6fe
Summary:The AlertViewIOS component takes in a 'defaultValue' for the text input but never actually sets it, this PR actually sets the value.
Closes https://github.com/facebook/react-native/pull/6257
Differential Revision: D3052412
Pulled By: nicklockwood
fb-gh-sync-id: 32285330f17ccf47189dbc8fcab48f3712fee59b
shipit-source-id: 32285330f17ccf47189dbc8fcab48f3712fee59b
Summary:This rev adds support for production sourcemaps on RAM.
When we inject a module into JSC we use the original `sourceURL` and specify the `startingLineNumber` of the module relative to a "regular" bundle. By doing so, when an error is thrown, JSC will include the provided `sourceURL` as the filename and will use the indicated `startingLineNumber` to figure out on which line the error actually occurred.
To make things a bit simpler and avoid having to deal with columns, we tweak the generated bundle so that each module starts on a new line. Since we cannot assure that each module's code will be on a single line as the minifier might break it on multiple (UglifyJS does so due to a bug on old versions of Chrome), we include on the index the line number that should be used when invoking `JSEvaluateScript`. Since the module length was not being used we replaced the placeholder we have there for the line number.
Reviewed By: javache
Differential Revision: D2997520
fb-gh-sync-id: 3243a489cbb5b48a963f4ccdd98ba63b30f53f3f
shipit-source-id: 3243a489cbb5b48a963f4ccdd98ba63b30f53f3f
Summary:At the moment, to initialize a React Native app, the entire JS bundle needs to be loaded. Parsing JS code takes a while which makes paying for every feature the app has very expensive on start up. Even worse, as the bundle gets bigger and bigger because the app has more and more features, start up time becomes slower.
This rev introduces the few remaining pieces of infrastructure to load JS modules incrementally. This way, on start up we only inject into JSC the modules we actually need. More importantly, by using this piece of infrastructure, the app start up time won't be affected as the JS bundle increases it's size.
Props to davidaurelio and tadeuzagallo for the original work. I'm just wrapping their work.
Differential Revision: D2995425
fb-gh-sync-id: caaaa880b5370c3bb36a11ae694dc303cd53d0e2
shipit-source-id: caaaa880b5370c3bb36a11ae694dc303cd53d0e2
Summary:Fixes #6281
The JS executor is invalidated from `[RCTBatchedBridger stopLoadingWithError:]`
which prevented another blocks that depended on the executor to run in the bridge
invalidation.
Reviewed By: javache
Differential Revision: D3018299
fb-gh-sync-id: 4f482b9b697bfabd24b405398d25c72b9e1a3c84
shipit-source-id: 4f482b9b697bfabd24b405398d25c72b9e1a3c84
Summary:
public
Expose JS hooks to create flow events in systrace (the nice arrows to show async work flow) +
add support to the showing all the work enqueued from the JS thread as added in D2743733
Depends on D2743733
Reviewed By: jspahrsummers
Differential Revision: D2815293
fb-gh-sync-id: 4278f61a67a6e78cf2704bacce34b1389328c6df
Summary:
public
To make sourcemaps work on Hot Loading work, we'll need to be able to serve them for each module that is dynamically replaced. To do so we introduced a new parameter to the bundler, namely `entryModuleOnly` to decide whether or not to process the full dependency tree or just the module associated to the entry file. Also we need to add `//sourceMappingURL` to the HMR updates so that in case of an error the runtime retrieves the sourcemaps for the file on which an error occurred from the server.
Finally, we need to refactor a bit how we load the HMR updates into JSC. Unfortunately, if the code is eval'ed when an error is thrown, the line and column number are missing. This is a bug/missing feature in JSC. To walkaround the issue we need to eval the code on native. This adds a bit of complexity to HMR as for both platforms we'll have to have a thin module to inject code but I don't see any other alternative. when debugging this is not needed as Chrome supports sourceMappingURLs on eval'ed code
Reviewed By: javache
Differential Revision: D2841788
fb-gh-sync-id: ad9370d26894527a151cea722463e694c670227e
Summary:
public
This exposes a proper API for adding synchronous callbacks to JS, as an optional feature of the executor.
This is based on nicklockwood's work in D2764492, but avoids refactoring bridge/executor interactions for the time being, since we agree on this API and can move the actual callsites around later.
Reviewed By: nicklockwood
Differential Revision: D2799506
fb-gh-sync-id: af209d9a0be927f3404205feb16e59745cc37aec
Summary:
public
Expose JS hooks to create flow events in systrace (the nice arrows to show async work flow) +
add support to the showing all the work enqueued from the JS thread as added in D2743733
Depends on D2743733
Reviewed By: jspahrsummers
Differential Revision: D2773664
fb-gh-sync-id: 4a8854b17b4741b882f5f2cc425e4237a5e4b3eb
Summary:
public
Until we support this fature on OSS, don't show the menu option.
Reviewed By: vjeux
Differential Revision: D2791198
fb-gh-sync-id: 11b66d467c1ab784bbf549b893d0a3abd69e2741
Summary:
public
Implement all the necessary glue code for several diffs submitted before to get Hot Loading work end to end:
- Simplify `HMRClient`: we don't need to make it stateful allowing to enable and disable it because both when we enable and disable the interface we need to reload the bundle.
- On the native side we introduced a singleton to process the bundle URL. This new class might alter the url to include the `hot` attribute. I'm not 100% sure this is the best way to implement this but we cannot use `CTLSettings` for this as it's are not available on oss and I didn't want to contaminate `RCTBridge` with something specific to hot loading. Also, we could potentially use this processor for other things in the future. Please let me know if you don't like this approach or you have a better idea :).
- Use this processor to alter the default bundle URL and request a `hot` bundle when hot loading is enabled. Also make sure to enable the HMR interface when the client activates it on the dev menu.
- Add packager `hot` option.
- Include gaeron's `react-transform` on Facebook's JS transformer.
The current implementation couples a bit React Native to this feature because `react-transform-hmr` is required on `InitializeJavaScriptAppEngine`. Ideally, the packager should accept an additional list of requires and include them on the bundle among all their dependencies. Note this is not the same as the option `runBeforeMainModule` as that one only adds a require to the provided module but doesn't include all the dependencies that module amy have that the entry point doesn't. I'll address this in a follow up task to enable asap hot loading (9536142)
I had to remove 2 `.babelrc` files from `react-proxy` and `react-deep-force-update`. There's an internal task for fixing the underlaying issue to avoid doing this horrible hack (t9515889).
Reviewed By: vjeux
Differential Revision: D2790806
fb-gh-sync-id: d4b78a2acfa071d6b3accc2e6716ef5611ad4fda
Summary:
public
This diff adds infra to both the Packager and the running app to have a WebSocket based connection between them. This connection is toggled by a new dev menu item, namely `Enable/Disable Hot Loading`.
Reviewed By: vjeux
Differential Revision: D2787621
fb-gh-sync-id: d1dee769348e4830c28782e7b650d025f2b3a786
Summary:
public
Rename the executor to so it actually says something about the implementation.
Reviewed By: jspahrsummers, nicklockwood
Differential Revision: D2759688
fb-gh-sync-id: 5b1ac447e75109fbbc2ee71c804710d9926785aa
Summary:
public
Rename `RCTPerformanceNow` to `nativePerformanceNow` to be consistent with Android
and the pattern we've been following where the native functions exposed to JSC
are prefixed with `native`.
Also change it to return fractional milliseconds, as the web (`performance.now`)
does: https://developer.mozilla.org/en-US/docs/Web/API/Performance/now
Reviewed By: mikearmstrong001
Differential Revision: D2755287
fb-gh-sync-id: 2acada5673633858ae0bbcdcfae554183e36cb24
Summary:
public
A lot of the core modules have to use private methods in the bridge, specially
since the `RCTBatchedBridge` interface is never exposed. That was leading to a
lot of different private bridge categories spread across different modules,
which makes harder to identify which modules are affected by private API changes.
Replace all the categories with a single private header.
Reviewed By: nicklockwood
Differential Revision: D2757564
fb-gh-sync-id: 793158b9082d542b74a6094ed0db4d5dc3a88f78
Summary:
public
Clean up the `RCTContextExecutor` a little bit by converting the exposed hooks to use the ObjC API.
Reviewed By: nicklockwood
Differential Revision: D2757363
fb-gh-sync-id: c6f5f53c5c1adb78af1cdb449268b6b3cc9740e8
Summary:
Extract JSC profiler API which can now be used even if profiler is unavailable.
public
Reviewed By: tadeuzagallo
Differential Revision: D2749217
fb-gh-sync-id: 1ffa6f37323ea0ddbda3fdacfdf8a9b360185b2e
Summary:
BridgeProfiling.setEnabled used a one off eval. Let's use the bridge to do this like everything else. This is already what the Android equivalent is doing.
public
Reviewed By: tadeuzagallo
Differential Revision: D2745059
fb-gh-sync-id: 5b633365b8cfc8abc6b80255e82ef3053ead9b50
Summary:
public
Rename the `BridgeProfiling` JS module to `Systrace`, since it's actually just
an API to Systrace markers.
This should make it clearer as we add more perf tooling.
Reviewed By: jspahrsummers
Differential Revision: D2734001
fb-gh-sync-id: 642848fa7340c545067f2a7cf5cef8af1c8a69a2
Summary:
public
More people wanted to understand the motivation behind the intentional retain
cycle in `RCTJavaScriptContext`, add a small comment with some context.
Reviewed By: jspahrsummers
Differential Revision: D2738930
fb-gh-sync-id: d8c950778eb6bf3eaca627aabb6c98335d25d1fc
Summary:
The JavaScript ecosystem doesn't have the notion of a built-in native module loader. Even Node is decoupled from its module loader. The module loader system is just JS that runs on top of the global `process` object which has all the built-in goodies.
Additionally there is no such thing as a global require. That is something unique to our providesModule system. In other module systems such as node, every require is contextual. Even registered npm names are localized by version.
The only global namespace that is accessible to the host environment is the global object. Normally module systems attaches itself onto the hooks provided by the host environment on the global object.
Currently, we have two forms of dispatch that reaches directly into the module system. executeJSCall which reaches directly into require. Everything now calls through the BatchedBridge module (except one RCTLog edge case that I will fix). I propose that the executors calls directly onto `BatchedBridge` through an instance on the global so that everything is guaranteed to go through it. It becomes the main communication hub.
I also propose that we drop the dynamic requires inside of MessageQueue/BatchBridge and instead have the modules register themselves with the bridge.
executeJSCall was originally modeled after the XHP equivalent. The XHP equivalent was designed that way because the act of doing the call was the thing that defined a dependency on the module from the page. However, that is not how React Native works.
The JS side is driving the dependencies by virtue of requiring new modules and frameworks and the existence of dependencies is driven by the JS side, so this design doesn't make as much sense.
The main driver for this is to be able to introduce a new module system like Prepack's module system. However, it also unlocks the possibility to do dead module elimination even in our current module system. It is currently not possible because we don't know which module might be called from native.
Since the module system now becomes decoupled we could publish all our providesModule modules as npm/CommonJS modules using a rewrite script. That's what React Core does.
That way people could use any CommonJS bundler such as Webpack, Closure Compiler, Rollup or some new innovation to create a JS bundle.
This diff expands the executeJSCalls to the BatchedBridge's three individual pieces to make them first class instead of being dynamic. This removes one layer of abstraction. Hopefully we can also remove more of the things that register themselves with the BatchedBridge (various EventEmitters) and instead have everything go through the public protocol. ReactMethod/RCT_EXPORT_METHOD.
public
Reviewed By: vjeux
Differential Revision: D2717535
fb-gh-sync-id: 70114f05483124f5ac5c4570422bb91a60a727f6
Summary: This thread is effectively the "main thread" for JavaScript code in React Native applications, so it should have as high a quality-of-service as possible.
public
Reviewed By: javache, nicklockwood
Differential Revision: D2641878
fb-gh-sync-id: 3c60c1abeeab9e7405d6fc9602e0d4ccfab1ea1b
Summary: public
The WebView executor has no benefits compared to the JSC executor (slower, no extra debugging tools...),
and it's pretty hacky (since it injects the code in a script tag we have to check for tags in the comments and etc...).
Reviewed By: nicklockwood, javache
Differential Revision: D2636465
fb-gh-sync-id: 0d0f8a59e2c12fe7905b02060b3938c894d2802b
Summary: public
Rename it to `RCT_PROFILE_(BEGIN|END)_EVENT` to make it clearer that it's a macro,
since it has special behaviours.
Reviewed By: jspahrsummers
Differential Revision: D2631542
fb-gh-sync-id: 629c139462c4aa3582f719b14482017d13676e33
Summary: public
For "some" reason, exception is never `NULL`, it's `null` (the JavaScript value),
so the calls will never finish.
Reviewed By: javache
Differential Revision: D2625896
fb-gh-sync-id: fc8176a6ac485bfecc9903db05bf69b39ac2d9b4
Summary: public
Added lightweight genarics annotations to make the code more readable and help the compiler catch bugs.
Fixed some type bugs and improved bridge validation in a few places.
Reviewed By: javache
Differential Revision: D2600189
fb-gh-sync-id: f81e22f2cdc107bf8d0b15deec6d5b83aacc5b56
Summary: public
Expose a more precise timer, millisecond precision is enough to measure small operations.
Reviewed By: javache
Differential Revision: D2604218
fb-gh-sync-id: ba50c891b5690575548fe04ba1ae7d015bc31d90
Summary: public
We moved to using `new` instead of `alloc] init` but there was still some calls
left.
Reviewed By: javache
Differential Revision: D2604679
fb-gh-sync-id: ff7300ecbedb55dd5e93873592598810c9b87808
Summary: public
After reloading the JS side of the profiler wasn't being reenabled.
Reviewed By: javache
Differential Revision: D2602258
fb-gh-sync-id: 5de8afb829e9fa8225600e2b0ff9e00313ac1d4c
Summary: public
Implement the iOS side of the optmisation previously implemented in android
(D2485402)
Depends on D2540746
Reviewed By: javache
Differential Revision: D2541118
fb-gh-sync-id: f3590600a6defa2da75c5b7b2cced6ad8bfea6cb
Summary: The Obj-C API is usually easier to work with, and also makes it very easy to use the C API when necessary (performance, for example). This diff just switches the designated initializer of RCTContextExecutor to take a JSContext instead of JSGlobalContextRef, but the old initializer still works if needed.
I was doing some memory leak investigation and it is easier with ARC so I wanted to incrementally move the executor to Obj-C.
Closes https://github.com/facebook/react-native/pull/2159
Reviewed By: svcscm
Differential Revision: D2554890
Pulled By: tadeuzagallo
fb-gh-sync-id: 75b96d04cddff68fa3daf5d0fafdffad21dae307
Summary: public
Benchmarking our startup path has shown we spend a lot of time decoding strings (iPhone 4S / iPhone 5):
* reading a 2MB JS bundle: 35ms / 15ms
* decoding is to an `NSString`: 186ms / 78ms
* transforming that to a `JSString`: 29ms / 10ms
Instead of going through an `NSString` transformation, we generate a null-terminated bundle (0.1ms / 0.05ms to copy the data) and use `JSStringCreateWithUTF8CString` (121ms / 53ms) to generate the string. That makes decoding 70% faster.
Reviewed By: javache
Differential Revision: D2541140
fb-gh-sync-id: 09a016b8edfd46a9b62682c76705564d2024e75e
Summary: @public
Take a step back and de-batch the bridge calls so we can have better profiling data and a better starting point to work on future optimisations. Also gave a 10~15% win on first render.
Reviewed By: @javache
Differential Revision: D2493674
fb-gh-sync-id: 05165fdd00645bdf43e844bb0c4300a2f63e7038
Summary: @public
The RCTDevMenu always calls the handler, even with the state hasn't changed.
Guard against it.
Reviewed By: @javache
Differential Revision: D2499034
Summary: This API is defined only on iOS 8 and newer. There is a warning that the function is defined when checking if it exists since it is always defined in the iOS 8 SDK but not necessarily on iOS 7 phones. Use pragmas to silence the warning.
Closes https://github.com/facebook/react-native/pull/2475
Reviewed By: @trunkagent, @vjeux
Differential Revision: D2443432
Pulled By: @tadeuzagallo
Summary: @public
Using the saved state of the toggle button, this starts profiling automatically when the `RCTContextExecutor` is set up, if it was profiling before.
Reviewed By: @tadeuzagallo
Differential Revision: D2429026
Summary: @public
Migrate scripts to open source and add new route on the packager
to directly convert profiler outputs to a devtools compatible format.
Reviewed By: @jspahrsummers
Differential Revision: D2425740
Summary: @public
* Change the JSON generation and remove the dependency on YAJL since it had a
128 depth limit
* Enable the profiler bytecode generation to fix missing frames
* Save the output to a file on the tmp dir instead of outputting it to the console
Reviewed By: @jspahrsummers
Differential Revision: D2420754
Summary:
Fixes#2464
After the bridge parallelisation of the bridge initialisation the executors
were being `setUp` in a background thread, and the `RCTWebViewExecutor` was
crashing when creating a `UIWebView` out of the main thread.
Wrap the `UIWebView` creation in a call to the main thread.
Summary:
Add JSC profiler to the dev menu and rename the pre-existent one to systrace.
For now it just outputs to the console, but a better workflow is on the way.
Summary:
Our events all follow a common pattern, so there's no good reason why the configuration should be so verbose. This diff eliminates that redundancy, and gives us the freedom to simplify the underlying mechanism in future without further churning the call sites.
Summary:
Add a method that lets JS set the name of the JSContext for debugging purposes. I check `JSGlobalContextSetName` since it is not available on iOS 7.
Closes https://github.com/facebook/react-native/pull/2144
Github Author: James Ide <ide@jameside.com>
Summary:
`NSProcessInfo operatingSystemVersion` was being used to check the system version
for the Legacy Profiler on `RCTContextExecutor` but it's only available on iOS8+
Change it to `[UIDevice systemVersion]`
Summary:
The context wasn't being explicitly released before, since it'd be immediately
released. Now that the executors are bridge modules, it was only being deallocated
when the modules were released, what caused the threads to not be released at all.
Summary:
Remove `RCTGetExecutorID` and `RCTSetExecutorID`, it wasn't used anymore since
the bridge was refactored into `RCTBridge` and `RCTBatchedBridge`.
Summary:
The context wasn't being explicitly released before, since it'd be immediately
released. Now that the executors are bridge modules, it was only being deallocated
when the modules were released, what caused the threads to not be released at all.
Summary:
@public
Add PerformanceLogger to keep track of JS download, initial script execution and
full TTI.
Test Plan:
The Native side currently calls `addTimespans` when it's finish initializing
with the six values (start and end for the three events), so I just checked it
with a `PerformanceLogger.logTimespans()` at the end of the function.
```
2015-06-18 16:47:19.096 [info][tid:com.facebook.React.JavaScript] "ScriptDownload: 48ms"
2015-06-18 16:47:19.096 [info][tid:com.facebook.React.JavaScript] "ScriptExecution: 106ms"
2015-06-18 16:47:19.096 [info][tid:com.facebook.React.JavaScript] "TTI: 293ms"
```
Summary:
@public
This removes the last piece of data that was still stored on the DATA section,
`RCT_IMPORT_METHOD`. JS calls now dynamically populate a lookup table simultaneously
on JS and Native, instead of creating a mapping at load time.
Test Plan: Everything still runs, tests are green.
Summary:
@public
I've increased the warning levels in the OSS frameworks, which caught a bunch of minor issues. I also fixed some new errors in Xcode 7 relating to designated initializers and TLS security.
Test Plan:
* Test the sample apps and make sure they still work.
* Run tests.
Summary:
@public
`-[RCTJavaScriptExecutor executeBlockOnJavaScriptQueue:]` would always `dispatch_async`
for the WebView and WebSocket executors, what caused for any frame aligned dispatch.
Test Plan:
Test the `Timers, TimerMixin` example on UIExplorer, `requestAnimationFrame` was
taking ~33.3ms when debugging, now takes ~16.6ms as expected.
Summary:
@public
Remove extra `JSGlobalContextRetain` that was causing the context ref to leak +
remove `self` reference from block and improve invalidation
Test Plan:
Run the UIExplorer, reload the app a few times, verify that the memory usage is
not increasing.
Summary:
@public
This is the first of a few diffs that change the way the executors are handled
by the bridge.
For they are just promoted to modules, so they are automatically loaded by the bridge.
Test Plan:
Tested on UIExplorer, Catalyst and MAdMan.
Tested all the 3 executors, everything looks fine.
Summary:
@public
Right now the profiler shows how long the executor took on JS but doesn't show
how long each of the batched calls took, this adds a *very* high level view of JS
execution (still doesn't show properly calls dispatched with setImmediate)
Also added a global property on JS to avoid trips to Native when profiling is
disabled.
Test Plan:
Run the Profiler on any app
{F22491690}
Summary:
This converts the existing JSEvaluateScript call for `require('<ModuleName>').<MethodName>.apply(null, <args>);` to native JSC C API methods which shaves off about 10-15% of invocation time on average, I used pretty primitive profiling methods to track the minimum, maximum and average invocation time so would appreciate any extra eyes on the performance.
If the argument count is zero the method is invoked directly with no arguments, if the argument count is 1 it's invoked directly with just that argument. If there is more than 1 argument then apply is used and the arguments are passed as the second parameter.
Ensured all existing tests pass and instruments leaks shows nothing is leaking.
Closes https://github.com/facebook/react-native/pull/1037
Github Author: Robert Payne <robertpayne@me.com>
Test Plan: Imported from GitHub, without a `Test Plan:` line.