From bb625e523867d3b8391a76e5aa7c22c081036835 Mon Sep 17 00:00:00 2001 From: Christoph Nakazawa Date: Fri, 16 Aug 2019 09:59:57 -0700 Subject: [PATCH] Remove the native delta client from Android Summary: This was an experiment to patch individual deltas in development instead of reloading the whole JS bundle. With improvements such as Fast Refresh that reduces the need for reloads and bundle splitting that reduces the number of modules and memory by 10x, we won't be needing this complex optimization that we never properly made work. This diff removes that code and I will be removing the JS side of things in Metro in a follow-up diff. Reviewed By: fkgozali Differential Revision: D16832709 fbshipit-source-id: 46596a3126d52d7d74f4b9ffc9a6ee9d82ec9522 --- .../facebook/react/ReactInstanceManager.java | 16 +- .../react/bridge/CatalystInstanceImpl.java | 10 - .../facebook/react/bridge/JSBundleLoader.java | 22 -- .../react/bridge/JSBundleLoaderDelegate.java | 11 - .../react/bridge/NativeDeltaClient.java | 25 -- .../react/devsupport/BundleDeltaClient.java | 202 ---------------- .../react/devsupport/BundleDownloader.java | 76 +----- .../react/devsupport/DevInternalSettings.java | 38 --- .../react/devsupport/DevServerHelper.java | 21 +- .../devsupport/DevSupportManagerImpl.java | 7 +- .../ReactInstanceManagerDevHelper.java | 3 +- .../interfaces/DevBundleDownloadListener.java | 3 +- .../jni/react/jni/CatalystInstanceImpl.cpp | 216 ++++++++++-------- .../main/jni/react/jni/CatalystInstanceImpl.h | 56 +++-- .../main/jni/react/jni/NativeDeltaClient.cpp | 57 ----- .../main/jni/react/jni/NativeDeltaClient.h | 41 ---- .../src/main/jni/react/jni/OnLoad.cpp | 35 +-- .../res/devsupport/xml/rn_dev_preferences.xml | 18 +- .../devsupport/BundleDeltaClientTest.java | 135 ----------- 19 files changed, 197 insertions(+), 795 deletions(-) delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/bridge/NativeDeltaClient.java delete mode 100644 ReactAndroid/src/main/java/com/facebook/react/devsupport/BundleDeltaClient.java delete mode 100644 ReactAndroid/src/main/jni/react/jni/NativeDeltaClient.cpp delete mode 100644 ReactAndroid/src/main/jni/react/jni/NativeDeltaClient.h delete mode 100644 ReactAndroid/src/test/java/com/facebook/react/devsupport/BundleDeltaClientTest.java diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index ec98de63758..48dcbc93471 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -56,7 +56,6 @@ import com.facebook.react.bridge.JSIModuleType; import com.facebook.react.bridge.JavaJSExecutor; import com.facebook.react.bridge.JavaScriptExecutor; import com.facebook.react.bridge.JavaScriptExecutorFactory; -import com.facebook.react.bridge.NativeDeltaClient; import com.facebook.react.bridge.NativeModuleCallExceptionHandler; import com.facebook.react.bridge.NativeModuleRegistry; import com.facebook.react.bridge.NotThreadSafeBridgeIdleDebugListener; @@ -279,8 +278,8 @@ public class ReactInstanceManager { } @Override - public void onJSBundleLoadedFromServer(@Nullable NativeDeltaClient nativeDeltaClient) { - ReactInstanceManager.this.onJSBundleLoadedFromServer(nativeDeltaClient); + public void onJSBundleLoadedFromServer() { + ReactInstanceManager.this.onJSBundleLoadedFromServer(); } @Override @@ -389,7 +388,7 @@ public class ReactInstanceManager { && !devSettings.isRemoteJSDebugEnabled()) { // If there is a up-to-date bundle downloaded from server, // with remote JS debugging disabled, always use that. - onJSBundleLoadedFromServer(null); + onJSBundleLoadedFromServer(); } else { // If dev server is down, disable the remote JS debugging. devSettings.setRemoteJSDebugEnabled(false); @@ -883,15 +882,12 @@ public class ReactInstanceManager { } @ThreadConfined(UI) - private void onJSBundleLoadedFromServer(@Nullable NativeDeltaClient nativeDeltaClient) { + private void onJSBundleLoadedFromServer() { Log.d(ReactConstants.TAG, "ReactInstanceManager.onJSBundleLoadedFromServer()"); JSBundleLoader bundleLoader = - nativeDeltaClient == null - ? JSBundleLoader.createCachedBundleFromNetworkLoader( - mDevSupportManager.getSourceUrl(), mDevSupportManager.getDownloadedJSBundleFile()) - : JSBundleLoader.createDeltaFromNetworkLoader( - mDevSupportManager.getSourceUrl(), nativeDeltaClient); + JSBundleLoader.createCachedBundleFromNetworkLoader( + mDevSupportManager.getSourceUrl(), mDevSupportManager.getDownloadedJSBundleFile()); recreateReactContextInBackground(mJavaScriptExecutorFactory, bundleLoader); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java index d2aa466665d..c2da5a77e5f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java @@ -233,13 +233,6 @@ public class CatalystInstanceImpl implements CatalystInstance { jniLoadScriptFromFile(fileName, sourceURL, loadSynchronously); } - @Override - public void loadScriptFromDeltaBundle( - String sourceURL, NativeDeltaClient deltaClient, boolean loadSynchronously) { - mSourceURL = sourceURL; - jniLoadScriptFromDeltaBundle(sourceURL, deltaClient, loadSynchronously); - } - private native void jniSetSourceURL(String sourceURL); private native void jniRegisterSegment(int segmentId, String path); @@ -250,9 +243,6 @@ public class CatalystInstanceImpl implements CatalystInstance { private native void jniLoadScriptFromFile( String fileName, String sourceURL, boolean loadSynchronously); - private native void jniLoadScriptFromDeltaBundle( - String sourceURL, NativeDeltaClient deltaClient, boolean loadSynchronously); - @Override public void runJSBundle() { Log.d(ReactConstants.TAG, "CatalystInstanceImpl.runJSBundle()"); diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/JSBundleLoader.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/JSBundleLoader.java index 12b35eb17a8..c83a40766a0 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/JSBundleLoader.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/JSBundleLoader.java @@ -72,28 +72,6 @@ public abstract class JSBundleLoader { }; } - /** - * This loader is used to load delta bundles from the dev server. We pass each delta message to - * the loader and process it in C++. Passing it as a string leads to inefficiencies due to memory - * copies, which will have to be addressed in a follow-up. - * - * @param nativeDeltaClient - */ - public static JSBundleLoader createDeltaFromNetworkLoader( - final String sourceURL, final NativeDeltaClient nativeDeltaClient) { - return new JSBundleLoader() { - @Override - public String loadScript(JSBundleLoaderDelegate delegate) { - try { - delegate.loadScriptFromDeltaBundle(sourceURL, nativeDeltaClient, false); - return sourceURL; - } catch (Exception e) { - throw DebugServerException.makeGeneric(sourceURL, e.getMessage(), e); - } - } - }; - } - /** * This loader is used when proxy debugging is enabled. In that case there is no point in fetching * the bundle from device as remote executor will have to do it anyway. diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/JSBundleLoaderDelegate.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/JSBundleLoaderDelegate.java index b21c5b6887d..d4e6bb1cb93 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/JSBundleLoaderDelegate.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/JSBundleLoaderDelegate.java @@ -32,17 +32,6 @@ public interface JSBundleLoaderDelegate { */ void loadScriptFromFile(String fileName, String sourceURL, boolean loadSynchronously); - /** - * Load a delta bundle from Metro. See {@link JSBundleLoader#createDeltaFromNetworkLoader(String, - * NativeDeltaClient)} - * - * @param sourceURL - * @param deltaClient - * @param loadSynchronously - */ - void loadScriptFromDeltaBundle( - String sourceURL, NativeDeltaClient deltaClient, boolean loadSynchronously); - /** * This API is used in situations where the JS bundle is being executed not on the device, but on * a host machine. In that case, we must provide two source URLs for the JS bundle: One to be used diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/NativeDeltaClient.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/NativeDeltaClient.java deleted file mode 100644 index 39ebf53b636..00000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/NativeDeltaClient.java +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - */ -package com.facebook.react.bridge; - -import com.facebook.jni.HybridData; -import java.nio.channels.ReadableByteChannel; - -public class NativeDeltaClient { - static { - ReactBridge.staticInit(); - } - - // C++ parts - private final HybridData mHybridData = initHybrid(); - - private static native HybridData initHybrid(); - - public native void reset(); - - public native void processDelta(ReadableByteChannel deltaMessage); -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/BundleDeltaClient.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/BundleDeltaClient.java deleted file mode 100644 index 5dceb37de0e..00000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/BundleDeltaClient.java +++ /dev/null @@ -1,202 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - */ -package com.facebook.react.devsupport; - -import android.util.JsonReader; -import android.util.Pair; -import androidx.annotation.Nullable; -import com.facebook.react.bridge.NativeDeltaClient; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.TreeMap; -import okhttp3.Headers; -import okio.BufferedSource; - -public abstract class BundleDeltaClient { - - private static final String METRO_DELTA_ID_HEADER = "X-Metro-Delta-ID"; - @Nullable private String mRevisionId; - - public enum ClientType { - NONE, - DEV_SUPPORT, - NATIVE - } - - static boolean isDeltaUrl(String bundleUrl) { - return bundleUrl.indexOf(".delta?") != -1; - } - - @Nullable - static BundleDeltaClient create(ClientType type) { - switch (type) { - case DEV_SUPPORT: - return new BundleDeltaJavaClient(); - case NATIVE: - return new BundleDeltaNativeClient(); - } - return null; - } - - public abstract boolean canHandle(ClientType type); - - protected abstract Pair processDelta( - BufferedSource body, File outputFile) throws IOException; - - public final synchronized String extendUrlForDelta(String bundleURL) { - return mRevisionId != null ? bundleURL + "&revisionId=" + mRevisionId : bundleURL; - } - - public synchronized void reset() { - mRevisionId = null; - } - - public synchronized Pair processDelta( - Headers headers, BufferedSource body, File outputFile) throws IOException { - - mRevisionId = headers.get(METRO_DELTA_ID_HEADER); - return processDelta(body, outputFile); - } - - private static class BundleDeltaJavaClient extends BundleDeltaClient { - - byte[] mPreCode; - byte[] mPostCode; - final TreeMap mModules = new TreeMap(); - - @Override - public boolean canHandle(ClientType type) { - return type == ClientType.DEV_SUPPORT; - } - - public synchronized void reset() { - super.reset(); - mPreCode = null; - mPostCode = null; - mModules.clear(); - } - - @Override - public synchronized Pair processDelta( - BufferedSource body, File outputFile) throws IOException { - JsonReader jsonReader = new JsonReader(new InputStreamReader(body.inputStream())); - jsonReader.beginObject(); - int numChangedModules = 0; - - while (jsonReader.hasNext()) { - String name = jsonReader.nextName(); - if (name.equals("pre")) { - mPreCode = jsonReader.nextString().getBytes(); - } else if (name.equals("post")) { - mPostCode = jsonReader.nextString().getBytes(); - } else if (name.equals("modules")) { - numChangedModules += setModules(jsonReader, mModules); - } else if (name.equals("added")) { - numChangedModules += setModules(jsonReader, mModules); - } else if (name.equals("modified")) { - numChangedModules += setModules(jsonReader, mModules); - } else if (name.equals("deleted")) { - numChangedModules += removeModules(jsonReader, mModules); - } else { - jsonReader.skipValue(); - } - } - - jsonReader.endObject(); - jsonReader.close(); - - if (numChangedModules == 0) { - // If we receive an empty delta, we don't need to save the file again (it'll have the - // same content). - return Pair.create(Boolean.FALSE, null); - } - - FileOutputStream fileOutputStream = new FileOutputStream(outputFile); - - try { - fileOutputStream.write(mPreCode); - fileOutputStream.write('\n'); - - for (byte[] code : mModules.values()) { - fileOutputStream.write(code); - fileOutputStream.write('\n'); - } - - fileOutputStream.write(mPostCode); - fileOutputStream.write('\n'); - } finally { - fileOutputStream.flush(); - fileOutputStream.close(); - } - - return Pair.create(Boolean.TRUE, null); - } - - private static int setModules(JsonReader jsonReader, TreeMap map) - throws IOException { - jsonReader.beginArray(); - - int numModules = 0; - while (jsonReader.hasNext()) { - jsonReader.beginArray(); - - int moduleId = jsonReader.nextInt(); - - map.put(moduleId, jsonReader.nextString().getBytes()); - - jsonReader.endArray(); - numModules++; - } - - jsonReader.endArray(); - - return numModules; - } - - private static int removeModules(JsonReader jsonReader, TreeMap map) - throws IOException { - jsonReader.beginArray(); - - int numModules = 0; - while (jsonReader.hasNext()) { - int moduleId = jsonReader.nextInt(); - - map.remove(moduleId); - - numModules++; - } - - jsonReader.endArray(); - - return numModules; - } - } - - private static class BundleDeltaNativeClient extends BundleDeltaClient { - private final NativeDeltaClient nativeClient = new NativeDeltaClient(); - - @Override - public boolean canHandle(ClientType type) { - return type == ClientType.NATIVE; - } - - @Override - protected Pair processDelta(BufferedSource body, File outputFile) - throws IOException { - nativeClient.processDelta(body); - return Pair.create(Boolean.FALSE, nativeClient); - } - - @Override - public void reset() { - super.reset(); - nativeClient.reset(); - } - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/BundleDownloader.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/BundleDownloader.java index 6478591c588..f5984bc8bb2 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/BundleDownloader.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/BundleDownloader.java @@ -7,11 +7,9 @@ package com.facebook.react.devsupport; import android.util.Log; -import android.util.Pair; import androidx.annotation.Nullable; import com.facebook.common.logging.FLog; import com.facebook.infer.annotation.Assertions; -import com.facebook.react.bridge.NativeDeltaClient; import com.facebook.react.common.DebugServerException; import com.facebook.react.common.ReactConstants; import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener; @@ -41,12 +39,9 @@ public class BundleDownloader { private final OkHttpClient mClient; - private BundleDeltaClient mBundleDeltaClient; - private @Nullable Call mDownloadBundleFromURLCall; public static class BundleInfo { - private @Nullable String mDeltaClientName; private @Nullable String mUrl; private int mFilesChangedCount; @@ -59,7 +54,6 @@ public class BundleDownloader { try { JSONObject obj = new JSONObject(jsonStr); - info.mDeltaClientName = obj.getString("deltaClient"); info.mUrl = obj.getString("url"); info.mFilesChangedCount = obj.getInt("filesChangedCount"); } catch (JSONException e) { @@ -74,7 +68,6 @@ public class BundleDownloader { JSONObject obj = new JSONObject(); try { - obj.put("deltaClient", mDeltaClientName); obj.put("url", mUrl); obj.put("filesChangedCount", mFilesChangedCount); } catch (JSONException e) { @@ -85,10 +78,6 @@ public class BundleDownloader { return obj.toString(); } - public @Nullable String getDeltaClient() { - return mDeltaClientName; - } - public String getUrl() { return mUrl != null ? mUrl : "unknown"; } @@ -106,10 +95,8 @@ public class BundleDownloader { final DevBundleDownloadListener callback, final File outputFile, final String bundleURL, - final @Nullable BundleInfo bundleInfo, - final BundleDeltaClient.ClientType clientType) { - downloadBundleFromURL( - callback, outputFile, bundleURL, bundleInfo, clientType, new Request.Builder()); + final @Nullable BundleInfo bundleInfo) { + downloadBundleFromURL(callback, outputFile, bundleURL, bundleInfo, new Request.Builder()); } public void downloadBundleFromURL( @@ -117,12 +104,11 @@ public class BundleDownloader { final File outputFile, final String bundleURL, final @Nullable BundleInfo bundleInfo, - final BundleDeltaClient.ClientType clientType, Request.Builder requestBuilder) { final Request request = requestBuilder - .url(formatBundleUrl(bundleURL, clientType)) + .url(formatBundleUrl(bundleURL)) // FIXME: there is a bug that makes MultipartStreamReader to never find the end of the // multipart message. This temporarily disables the multipart mode to work around it, // but @@ -165,8 +151,7 @@ public class BundleDownloader { Matcher match = regex.matcher(contentType); try (Response r = response) { if (match.find()) { - processMultipartResponse( - url, r, match.group(1), outputFile, bundleInfo, clientType, callback); + processMultipartResponse(url, r, match.group(1), outputFile, bundleInfo, callback); } else { // In case the server doesn't support multipart/mixed responses, fallback to normal // download. @@ -177,7 +162,6 @@ public class BundleDownloader { Okio.buffer(r.body().source()), outputFile, bundleInfo, - clientType, callback); } } @@ -185,12 +169,8 @@ public class BundleDownloader { }); } - private String formatBundleUrl(String bundleURL, BundleDeltaClient.ClientType clientType) { - return BundleDeltaClient.isDeltaUrl(bundleURL) - && mBundleDeltaClient != null - && mBundleDeltaClient.canHandle(clientType) - ? mBundleDeltaClient.extendUrlForDelta(bundleURL) - : bundleURL; + private String formatBundleUrl(String bundleURL) { + return bundleURL; } private void processMultipartResponse( @@ -199,7 +179,6 @@ public class BundleDownloader { String boundary, final File outputFile, @Nullable final BundleInfo bundleInfo, - final BundleDeltaClient.ClientType clientType, final DevBundleDownloadListener callback) throws IOException { @@ -223,14 +202,7 @@ public class BundleDownloader { status = Integer.parseInt(headers.get("X-Http-Status")); } processBundleResult( - url, - status, - Headers.of(headers), - body, - outputFile, - bundleInfo, - clientType, - callback); + url, status, Headers.of(headers), body, outputFile, bundleInfo, callback); } else { if (!headers.containsKey("Content-Type") || !headers.get("Content-Type").equals("application/json")) { @@ -286,7 +258,6 @@ public class BundleDownloader { BufferedSource body, File outputFile, BundleInfo bundleInfo, - BundleDeltaClient.ClientType clientType, DevBundleDownloadListener callback) throws IOException { // Check for server errors. If the server error has the expected form, fail with more info. @@ -311,41 +282,19 @@ public class BundleDownloader { } if (bundleInfo != null) { - populateBundleInfo(url, headers, clientType, bundleInfo); + populateBundleInfo(url, headers, bundleInfo); } File tmpFile = new File(outputFile.getPath() + ".tmp"); - boolean bundleWritten; - NativeDeltaClient nativeDeltaClient = null; - - if (BundleDeltaClient.isDeltaUrl(url)) { - // If the bundle URL has the delta extension, we need to use the delta patching logic. - BundleDeltaClient deltaClient = getBundleDeltaClient(clientType); - Assertions.assertNotNull(deltaClient); - Pair result = deltaClient.processDelta(headers, body, tmpFile); - bundleWritten = result.first; - nativeDeltaClient = result.second; - } else { - mBundleDeltaClient = null; - bundleWritten = storePlainJSInFile(body, tmpFile); - } - - if (bundleWritten) { + if (storePlainJSInFile(body, tmpFile)) { // If we have received a new bundle from the server, move it to its final destination. if (!tmpFile.renameTo(outputFile)) { throw new IOException("Couldn't rename " + tmpFile + " to " + outputFile); } } - callback.onSuccess(nativeDeltaClient); - } - - private BundleDeltaClient getBundleDeltaClient(BundleDeltaClient.ClientType clientType) { - if (mBundleDeltaClient == null || !mBundleDeltaClient.canHandle(clientType)) { - mBundleDeltaClient = BundleDeltaClient.create(clientType); - } - return mBundleDeltaClient; + callback.onSuccess(); } private static boolean storePlainJSInFile(BufferedSource body, File outputFile) @@ -363,10 +312,7 @@ public class BundleDownloader { return true; } - private static void populateBundleInfo( - String url, Headers headers, BundleDeltaClient.ClientType clientType, BundleInfo bundleInfo) { - bundleInfo.mDeltaClientName = - clientType == BundleDeltaClient.ClientType.NONE ? null : clientType.name(); + private static void populateBundleInfo(String url, Headers headers, BundleInfo bundleInfo) { bundleInfo.mUrl = url; String filesChangedCountStr = headers.get("X-Metro-Files-Changed-Count"); diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevInternalSettings.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevInternalSettings.java index c4a48a4281b..4465e8a6e9d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevInternalSettings.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevInternalSettings.java @@ -6,7 +6,6 @@ */ package com.facebook.react.devsupport; -import android.annotation.SuppressLint; import android.content.Context; import android.content.SharedPreferences; import android.preference.PreferenceManager; @@ -27,8 +26,6 @@ public class DevInternalSettings private static final String PREFS_FPS_DEBUG_KEY = "fps_debug"; private static final String PREFS_JS_DEV_MODE_DEBUG_KEY = "js_dev_mode_debug"; private static final String PREFS_JS_MINIFY_DEBUG_KEY = "js_minify_debug"; - private static final String PREFS_JS_BUNDLE_DELTAS_KEY = "js_bundle_deltas"; - private static final String PREFS_JS_BUNDLE_DELTAS_CPP_KEY = "js_bundle_deltas_cpp"; private static final String PREFS_ANIMATIONS_DEBUG_KEY = "animations_debug"; // This option is no longer exposed in the dev menu UI. // It was renamed in D15958697 so it doesn't get stuck with no way to turn it off: @@ -42,24 +39,12 @@ public class DevInternalSettings private final SharedPreferences mPreferences; private final Listener mListener; private final PackagerConnectionSettings mPackagerConnectionSettings; - private final boolean mSupportsNativeDeltaClients; - - public static DevInternalSettings withoutNativeDeltaClient( - Context applicationContext, Listener listener) { - return new DevInternalSettings(applicationContext, listener, false); - } public DevInternalSettings(Context applicationContext, Listener listener) { - this(applicationContext, listener, true); - } - - private DevInternalSettings( - Context applicationContext, Listener listener, boolean supportsNativeDeltaClients) { mListener = listener; mPreferences = PreferenceManager.getDefaultSharedPreferences(applicationContext); mPreferences.registerOnSharedPreferenceChangeListener(this); mPackagerConnectionSettings = new PackagerConnectionSettings(applicationContext); - mSupportsNativeDeltaClients = supportsNativeDeltaClients; } public PackagerConnectionSettings getPackagerConnectionSettings() { @@ -99,8 +84,6 @@ public class DevInternalSettings if (PREFS_FPS_DEBUG_KEY.equals(key) || PREFS_RELOAD_ON_JS_CHANGE_KEY.equals(key) || PREFS_JS_DEV_MODE_DEBUG_KEY.equals(key) - || PREFS_JS_BUNDLE_DELTAS_KEY.equals(key) - || PREFS_JS_BUNDLE_DELTAS_CPP_KEY.equals(key) || PREFS_START_SAMPLING_PROFILER_ON_INIT.equals(key) || PREFS_JS_MINIFY_DEBUG_KEY.equals(key)) { mListener.onInternalSettingsChanged(); @@ -132,27 +115,6 @@ public class DevInternalSettings mPreferences.edit().putBoolean(PREFS_INSPECTOR_DEBUG_KEY, enabled).apply(); } - @SuppressLint("SharedPreferencesUse") - public boolean isBundleDeltasEnabled() { - return mPreferences.getBoolean(PREFS_JS_BUNDLE_DELTAS_KEY, false); - } - - @SuppressLint("SharedPreferencesUse") - public void setBundleDeltasEnabled(boolean enabled) { - mPreferences.edit().putBoolean(PREFS_JS_BUNDLE_DELTAS_KEY, enabled).apply(); - } - - @SuppressLint("SharedPreferencesUse") - public boolean isBundleDeltasCppEnabled() { - return mSupportsNativeDeltaClients - && mPreferences.getBoolean(PREFS_JS_BUNDLE_DELTAS_CPP_KEY, false); - } - - @SuppressLint("SharedPreferencesUse") - public void setBundleDeltasCppEnabled(boolean enabled) { - mPreferences.edit().putBoolean(PREFS_JS_BUNDLE_DELTAS_CPP_KEY, enabled).apply(); - } - @Override public boolean isNuclideJSDebugEnabled() { return ReactBuildConfig.IS_INTERNAL_BUILD && ReactBuildConfig.DEBUG; diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java index 09681da38cf..52c64777611 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java @@ -102,7 +102,6 @@ public class DevServerHelper { private enum BundleType { BUNDLE("bundle"), - DELTA("delta"), MAP("map"); private final String mTypeID; @@ -397,8 +396,7 @@ public class DevServerHelper { File outputFile, String bundleURL, BundleDownloader.BundleInfo bundleInfo) { - mBundleDownloader.downloadBundleFromURL( - callback, outputFile, bundleURL, bundleInfo, getDeltaClientType()); + mBundleDownloader.downloadBundleFromURL(callback, outputFile, bundleURL, bundleInfo); } public void downloadBundleFromURL( @@ -408,17 +406,7 @@ public class DevServerHelper { BundleDownloader.BundleInfo bundleInfo, Request.Builder requestBuilder) { mBundleDownloader.downloadBundleFromURL( - callback, outputFile, bundleURL, bundleInfo, getDeltaClientType(), requestBuilder); - } - - private BundleDeltaClient.ClientType getDeltaClientType() { - if (mSettings.isBundleDeltasCppEnabled()) { - return BundleDeltaClient.ClientType.NATIVE; - } else if (mSettings.isBundleDeltasEnabled()) { - return BundleDeltaClient.ClientType.DEV_SUPPORT; - } else { - return BundleDeltaClient.ClientType.NONE; - } + callback, outputFile, bundleURL, bundleInfo, requestBuilder); } /** @return the host to use when connecting to the bundle server from the host itself. */ @@ -475,7 +463,7 @@ public class DevServerHelper { public String getDevServerBundleURL(final String jsModulePath) { return createBundleURL( jsModulePath, - mSettings.isBundleDeltasEnabled() ? BundleType.DELTA : BundleType.BUNDLE, + BundleType.BUNDLE, mSettings.getPackagerConnectionSettings().getDebugServerHost()); } @@ -652,8 +640,7 @@ public class DevServerHelper { } public String getSourceUrl(String mainModuleName) { - return createBundleURL( - mainModuleName, mSettings.isBundleDeltasEnabled() ? BundleType.DELTA : BundleType.BUNDLE); + return createBundleURL(mainModuleName, BundleType.BUNDLE); } public String getJSBundleURLForRemoteDebugging(String mainModuleName) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerImpl.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerImpl.java index 70b3eb954d0..163e27e4ef6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerImpl.java @@ -30,7 +30,6 @@ import com.facebook.react.bridge.CatalystInstance; import com.facebook.react.bridge.DefaultNativeModuleCallExceptionHandler; import com.facebook.react.bridge.JavaJSExecutor; import com.facebook.react.bridge.JavaScriptExecutorFactory; -import com.facebook.react.bridge.NativeDeltaClient; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactMarker; import com.facebook.react.bridge.ReactMarkerConstants; @@ -1026,7 +1025,7 @@ public class DevSupportManagerImpl mDevServerHelper.downloadBundleFromURL( new DevBundleDownloadListener() { @Override - public void onSuccess(final @Nullable NativeDeltaClient nativeDeltaClient) { + public void onSuccess() { mDevLoadingViewController.hide(); mDevLoadingViewVisible = false; synchronized (DevSupportManagerImpl.this) { @@ -1034,7 +1033,7 @@ public class DevSupportManagerImpl mBundleStatus.updateTimestamp = System.currentTimeMillis(); } if (mBundleDownloadListener != null) { - mBundleDownloadListener.onSuccess(nativeDeltaClient); + mBundleDownloadListener.onSuccess(); } UiThreadUtil.runOnUiThread( new Runnable() { @@ -1042,7 +1041,7 @@ public class DevSupportManagerImpl public void run() { ReactMarker.logMarker( ReactMarkerConstants.DOWNLOAD_END, bundleInfo.toJSONString()); - mReactInstanceManagerHelper.onJSBundleLoadedFromServer(nativeDeltaClient); + mReactInstanceManagerHelper.onJSBundleLoadedFromServer(); } }); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/ReactInstanceManagerDevHelper.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/ReactInstanceManagerDevHelper.java index 6cb86590225..5807b243d00 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/ReactInstanceManagerDevHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/ReactInstanceManagerDevHelper.java @@ -10,7 +10,6 @@ import android.app.Activity; import androidx.annotation.Nullable; import com.facebook.react.bridge.JavaJSExecutor; import com.facebook.react.bridge.JavaScriptExecutorFactory; -import com.facebook.react.bridge.NativeDeltaClient; /** * Interface used by {@link DevSupportManager} for accessing some fields and methods of {@link @@ -22,7 +21,7 @@ public interface ReactInstanceManagerDevHelper { void onReloadWithJSDebugger(JavaJSExecutor.Factory proxyExecutorFactory); /** Notify react instance manager about new JS bundle version downloaded from the server. */ - void onJSBundleLoadedFromServer(@Nullable NativeDeltaClient nativeDeltaClient); + void onJSBundleLoadedFromServer(); /** Request to toggle the react element inspector. */ void toggleElementInspector(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/interfaces/DevBundleDownloadListener.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/interfaces/DevBundleDownloadListener.java index 8ddd20af41c..00ed879e355 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/interfaces/DevBundleDownloadListener.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/interfaces/DevBundleDownloadListener.java @@ -7,10 +7,9 @@ package com.facebook.react.devsupport.interfaces; import androidx.annotation.Nullable; -import com.facebook.react.bridge.NativeDeltaClient; public interface DevBundleDownloadListener { - void onSuccess(@Nullable NativeDeltaClient nativeDeltaClient); + void onSuccess(); void onProgress(@Nullable String status, @Nullable Integer done, @Nullable Integer total); diff --git a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp index 3782296ea28..1f03c154ae8 100644 --- a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp +++ b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp @@ -5,32 +5,31 @@ #include "CatalystInstanceImpl.h" -#include #include +#include #include #include +#include #include #include #include #include -#include #include #include #include -#include #include -#include +#include #include -#include +#include #include +#include #include #include -#include #include "CxxModuleWrapper.h" -#include "JavaScriptExecutorHolder.h" #include "JNativeRunnable.h" +#include "JavaScriptExecutorHolder.h" #include "JniJSModulesUnbundle.h" #include "NativeArray.h" @@ -48,14 +47,15 @@ class Exception : public jni::JavaClass { class JInstanceCallback : public InstanceCallback { public: explicit JInstanceCallback( - alias_ref jobj, - std::shared_ptr messageQueueThread) - : jobj_(make_global(jobj)), messageQueueThread_(std::move(messageQueueThread)) {} + alias_ref jobj, + std::shared_ptr messageQueueThread) + : jobj_(make_global(jobj)), + messageQueueThread_(std::move(messageQueueThread)) {} void onBatchComplete() override { messageQueueThread_->runOnQueue([this] { - static auto method = - ReactCallback::javaClassStatic()->getMethod("onBatchComplete"); + static auto method = ReactCallback::javaClassStatic()->getMethod( + "onBatchComplete"); method(jobj_); }); } @@ -65,15 +65,15 @@ class JInstanceCallback : public InstanceCallback { // managed by the module, via callJSCallback or callJSFunction. So, // we ensure that it is registered with the JVM. jni::ThreadScope guard; - static auto method = - ReactCallback::javaClassStatic()->getMethod("incrementPendingJSCalls"); + static auto method = ReactCallback::javaClassStatic()->getMethod( + "incrementPendingJSCalls"); method(jobj_); } void decrementPendingJSCalls() override { jni::ThreadScope guard; - static auto method = - ReactCallback::javaClassStatic()->getMethod("decrementPendingJSCalls"); + static auto method = ReactCallback::javaClassStatic()->getMethod( + "decrementPendingJSCalls"); method(jobj_); } @@ -82,15 +82,15 @@ class JInstanceCallback : public InstanceCallback { std::shared_ptr messageQueueThread_; }; -} +} // namespace -jni::local_ref CatalystInstanceImpl::initHybrid( - jni::alias_ref) { +jni::local_ref +CatalystInstanceImpl::initHybrid(jni::alias_ref) { return makeCxxInstance(); } CatalystInstanceImpl::CatalystInstanceImpl() - : instance_(folly::make_unique()) {} + : instance_(folly::make_unique()) {} CatalystInstanceImpl::~CatalystInstanceImpl() { if (moduleMessageQueue_ != NULL) { @@ -100,20 +100,34 @@ CatalystInstanceImpl::~CatalystInstanceImpl() { void CatalystInstanceImpl::registerNatives() { registerHybrid({ - makeNativeMethod("initHybrid", CatalystInstanceImpl::initHybrid), - makeNativeMethod("initializeBridge", CatalystInstanceImpl::initializeBridge), - makeNativeMethod("jniExtendNativeModules", CatalystInstanceImpl::extendNativeModules), - makeNativeMethod("jniSetSourceURL", CatalystInstanceImpl::jniSetSourceURL), - makeNativeMethod("jniRegisterSegment", CatalystInstanceImpl::jniRegisterSegment), - makeNativeMethod("jniLoadScriptFromAssets", CatalystInstanceImpl::jniLoadScriptFromAssets), - makeNativeMethod("jniLoadScriptFromFile", CatalystInstanceImpl::jniLoadScriptFromFile), - makeNativeMethod("jniLoadScriptFromDeltaBundle", CatalystInstanceImpl::jniLoadScriptFromDeltaBundle), - makeNativeMethod("jniCallJSFunction", CatalystInstanceImpl::jniCallJSFunction), - makeNativeMethod("jniCallJSCallback", CatalystInstanceImpl::jniCallJSCallback), - makeNativeMethod("setGlobalVariable", CatalystInstanceImpl::setGlobalVariable), - makeNativeMethod("getJavaScriptContext", CatalystInstanceImpl::getJavaScriptContext), - makeNativeMethod("getJSCallInvokerHolder", CatalystInstanceImpl::getJSCallInvokerHolder), - makeNativeMethod("jniHandleMemoryPressure", CatalystInstanceImpl::handleMemoryPressure), + makeNativeMethod("initHybrid", CatalystInstanceImpl::initHybrid), + makeNativeMethod( + "initializeBridge", CatalystInstanceImpl::initializeBridge), + makeNativeMethod( + "jniExtendNativeModules", CatalystInstanceImpl::extendNativeModules), + makeNativeMethod( + "jniSetSourceURL", CatalystInstanceImpl::jniSetSourceURL), + makeNativeMethod( + "jniRegisterSegment", CatalystInstanceImpl::jniRegisterSegment), + makeNativeMethod( + "jniLoadScriptFromAssets", + CatalystInstanceImpl::jniLoadScriptFromAssets), + makeNativeMethod( + "jniLoadScriptFromFile", CatalystInstanceImpl::jniLoadScriptFromFile), + makeNativeMethod( + "jniCallJSFunction", CatalystInstanceImpl::jniCallJSFunction), + makeNativeMethod( + "jniCallJSCallback", CatalystInstanceImpl::jniCallJSCallback), + makeNativeMethod( + "setGlobalVariable", CatalystInstanceImpl::setGlobalVariable), + makeNativeMethod( + "getJavaScriptContext", CatalystInstanceImpl::getJavaScriptContext), + makeNativeMethod( + "getJSCallInvokerHolder", + CatalystInstanceImpl::getJSCallInvokerHolder), + makeNativeMethod( + "jniHandleMemoryPressure", + CatalystInstanceImpl::handleMemoryPressure), }); JNativeRunnable::registerNatives(); @@ -122,18 +136,23 @@ void CatalystInstanceImpl::registerNatives() { void CatalystInstanceImpl::initializeBridge( jni::alias_ref callback, // This executor is actually a factory holder. - JavaScriptExecutorHolder* jseh, + JavaScriptExecutorHolder *jseh, jni::alias_ref jsQueue, jni::alias_ref nativeModulesQueue, - jni::alias_ref::javaobject> javaModules, - jni::alias_ref::javaobject> cxxModules) { + jni::alias_ref::javaobject> + javaModules, + jni::alias_ref::javaobject> + cxxModules) { // TODO mhorowitz: how to assert here? - // Assertions.assertCondition(mBridge == null, "initializeBridge should be called once"); - moduleMessageQueue_ = std::make_shared(nativeModulesQueue); + // Assertions.assertCondition(mBridge == null, "initializeBridge should be + // called once"); + moduleMessageQueue_ = + std::make_shared(nativeModulesQueue); // This used to be: // - // Java CatalystInstanceImpl -> C++ CatalystInstanceImpl -> Bridge -> Bridge::Callback + // Java CatalystInstanceImpl -> C++ CatalystInstanceImpl -> Bridge -> + // Bridge::Callback // --weak--> ReactCallback -> Java CatalystInstanceImpl // // Now the weak ref is a global ref. So breaking the loop depends on @@ -147,45 +166,46 @@ void CatalystInstanceImpl::initializeBridge( // don't need jsModuleDescriptions any more, all the way up and down the // stack. - moduleRegistry_ = std::make_shared( - buildNativeModuleList( - std::weak_ptr(instance_), - javaModules, - cxxModules, - moduleMessageQueue_)); + moduleRegistry_ = std::make_shared(buildNativeModuleList( + std::weak_ptr(instance_), + javaModules, + cxxModules, + moduleMessageQueue_)); instance_->initializeBridge( - std::make_unique( - callback, - moduleMessageQueue_), - jseh->getExecutorFactory(), - folly::make_unique(jsQueue), - moduleRegistry_); + std::make_unique(callback, moduleMessageQueue_), + jseh->getExecutorFactory(), + folly::make_unique(jsQueue), + moduleRegistry_); } void CatalystInstanceImpl::extendNativeModules( - jni::alias_ref::javaobject> javaModules, - jni::alias_ref::javaobject> cxxModules) { + jni::alias_ref::javaobject> + javaModules, + jni::alias_ref::javaobject> + cxxModules) { moduleRegistry_->registerModules(buildNativeModuleList( - std::weak_ptr(instance_), - javaModules, - cxxModules, - moduleMessageQueue_)); + std::weak_ptr(instance_), + javaModules, + cxxModules, + moduleMessageQueue_)); } -void CatalystInstanceImpl::jniSetSourceURL(const std::string& sourceURL) { +void CatalystInstanceImpl::jniSetSourceURL(const std::string &sourceURL) { instance_->setSourceURL(sourceURL); } -void CatalystInstanceImpl::jniRegisterSegment(int segmentId, const std::string& path) { +void CatalystInstanceImpl::jniRegisterSegment( + int segmentId, + const std::string &path) { instance_->registerBundle((uint32_t)segmentId, path); } void CatalystInstanceImpl::jniLoadScriptFromAssets( jni::alias_ref assetManager, - const std::string& assetURL, + const std::string &assetURL, bool loadSynchronously) { - const int kAssetsLength = 9; // strlen("assets://"); + const int kAssetsLength = 9; // strlen("assets://"); auto sourceURL = assetURL.substr(kAssetsLength); auto manager = extractAssetManager(assetManager); @@ -194,47 +214,37 @@ void CatalystInstanceImpl::jniLoadScriptFromAssets( auto bundle = JniJSModulesUnbundle::fromEntryFile(manager, sourceURL); auto registry = RAMBundleRegistry::singleBundleRegistry(std::move(bundle)); instance_->loadRAMBundle( - std::move(registry), - std::move(script), - sourceURL, - loadSynchronously); + std::move(registry), std::move(script), sourceURL, loadSynchronously); return; } else if (Instance::isIndexedRAMBundle(&script)) { instance_->loadRAMBundleFromString(std::move(script), sourceURL); } else { - instance_->loadScriptFromString(std::move(script), sourceURL, loadSynchronously); + instance_->loadScriptFromString( + std::move(script), sourceURL, loadSynchronously); } } -void CatalystInstanceImpl::jniLoadScriptFromFile(const std::string& fileName, - const std::string& sourceURL, - bool loadSynchronously) { +void CatalystInstanceImpl::jniLoadScriptFromFile( + const std::string &fileName, + const std::string &sourceURL, + bool loadSynchronously) { if (Instance::isIndexedRAMBundle(fileName.c_str())) { instance_->loadRAMBundleFromFile(fileName, sourceURL, loadSynchronously); } else { std::unique_ptr script; RecoverableError::runRethrowingAsRecoverable( - [&fileName, &script]() { - script = JSBigFileString::fromPath(fileName); - }); - instance_->loadScriptFromString(std::move(script), sourceURL, loadSynchronously); + [&fileName, &script]() { + script = JSBigFileString::fromPath(fileName); + }); + instance_->loadScriptFromString( + std::move(script), sourceURL, loadSynchronously); } } -void CatalystInstanceImpl::jniLoadScriptFromDeltaBundle( - const std::string& sourceURL, - jni::alias_ref jDeltaClient, - bool loadSynchronously) { - - auto deltaClient = jDeltaClient->cthis()->getDeltaClient(); - auto registry = RAMBundleRegistry::singleBundleRegistry( - folly::make_unique(deltaClient)); - - instance_->loadRAMBundle( - std::move(registry), deltaClient->getStartupCode(), sourceURL, loadSynchronously); -} - -void CatalystInstanceImpl::jniCallJSFunction(std::string module, std::string method, NativeArray* arguments) { +void CatalystInstanceImpl::jniCallJSFunction( + std::string module, + std::string method, + NativeArray *arguments) { // We want to share the C++ code, and on iOS, modules pass module/method // names as strings all the way through to JS, and there's no way to do // string -> id mapping on the objc side. So on Android, we convert the @@ -242,39 +252,45 @@ void CatalystInstanceImpl::jniCallJSFunction(std::string module, std::string met // used as ids if isFinite(), which handles this case, and looked up as // strings otherwise. Eventually, we'll probably want to modify the stack // from the JS proxy through here to use strings, too. - instance_->callJSFunction(std::move(module), - std::move(method), - arguments->consume()); + instance_->callJSFunction( + std::move(module), std::move(method), arguments->consume()); } -void CatalystInstanceImpl::jniCallJSCallback(jint callbackId, NativeArray* arguments) { +void CatalystInstanceImpl::jniCallJSCallback( + jint callbackId, + NativeArray *arguments) { instance_->callJSCallback(callbackId, arguments->consume()); } -void CatalystInstanceImpl::setGlobalVariable(std::string propName, - std::string&& jsonValue) { +void CatalystInstanceImpl::setGlobalVariable( + std::string propName, + std::string &&jsonValue) { // This is only ever called from Java with short strings, and only // for testing, so no need to try hard for zero-copy here. - instance_->setGlobalVariable(std::move(propName), - folly::make_unique(std::move(jsonValue))); + instance_->setGlobalVariable( + std::move(propName), + folly::make_unique(std::move(jsonValue))); } jlong CatalystInstanceImpl::getJavaScriptContext() { - return (jlong) (intptr_t) instance_->getJavaScriptContext(); + return (jlong)(intptr_t)instance_->getJavaScriptContext(); } void CatalystInstanceImpl::handleMemoryPressure(int pressureLevel) { instance_->handleMemoryPressure(pressureLevel); } -jni::alias_ref CatalystInstanceImpl::getJSCallInvokerHolder() { +jni::alias_ref +CatalystInstanceImpl::getJSCallInvokerHolder() { if (!javaInstanceHolder_) { jsCallInvoker_ = std::make_shared(instance_); - javaInstanceHolder_ = jni::make_global(JSCallInvokerHolder::newObjectCxxArgs(jsCallInvoker_)); + javaInstanceHolder_ = + jni::make_global(JSCallInvokerHolder::newObjectCxxArgs(jsCallInvoker_)); } return javaInstanceHolder_; } -}} +} // namespace react +} // namespace facebook diff --git a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h index dab2007434e..6c39ae90f5c 100644 --- a/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h +++ b/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h @@ -5,17 +5,16 @@ #include +#include +#include #include #include -#include -#include #include "CxxModuleWrapper.h" -#include "JavaModuleWrapper.h" #include "JMessageQueueThread.h" #include "JSLoader.h" +#include "JavaModuleWrapper.h" #include "ModuleRegistryBuilder.h" -#include "NativeDeltaClient.h" namespace facebook { namespace react { @@ -25,12 +24,14 @@ class JavaScriptExecutorHolder; class NativeArray; struct ReactCallback : public jni::JavaClass { - static constexpr auto kJavaDescriptor = "Lcom/facebook/react/bridge/ReactCallback;"; + static constexpr auto kJavaDescriptor = + "Lcom/facebook/react/bridge/ReactCallback;"; }; class CatalystInstanceImpl : public jni::HybridClass { public: - static constexpr auto kJavaDescriptor = "Lcom/facebook/react/bridge/CatalystInstanceImpl;"; + static constexpr auto kJavaDescriptor = + "Lcom/facebook/react/bridge/CatalystInstanceImpl;"; static jni::local_ref initHybrid(jni::alias_ref); ~CatalystInstanceImpl() override; @@ -49,35 +50,47 @@ class CatalystInstanceImpl : public jni::HybridClass { void initializeBridge( jni::alias_ref callback, // This executor is actually a factory holder. - JavaScriptExecutorHolder* jseh, + JavaScriptExecutorHolder *jseh, jni::alias_ref jsQueue, jni::alias_ref moduleQueue, - jni::alias_ref::javaobject> javaModules, - jni::alias_ref::javaobject> cxxModules); + jni::alias_ref< + jni::JCollection::javaobject> + javaModules, + jni::alias_ref::javaobject> + cxxModules); void extendNativeModules( - jni::alias_ref::javaobject> javaModules, - jni::alias_ref::javaobject> cxxModules); + jni::alias_ref::javaobject> javaModules, + jni::alias_ref::javaobject> + cxxModules); /** * Sets the source URL of the underlying bridge without loading any JS code. */ - void jniSetSourceURL(const std::string& sourceURL); + void jniSetSourceURL(const std::string &sourceURL); /** * Registers the file path of an additional JS segment by its ID. * */ - void jniRegisterSegment(int segmentId, const std::string& path); + void jniRegisterSegment(int segmentId, const std::string &path); - void jniLoadScriptFromAssets(jni::alias_ref assetManager, const std::string& assetURL, bool loadSynchronously); - void jniLoadScriptFromFile(const std::string& fileName, const std::string& sourceURL, bool loadSynchronously); - void jniLoadScriptFromDeltaBundle(const std::string& sourceURL, jni::alias_ref deltaClient, bool loadSynchronously); - void jniCallJSFunction(std::string module, std::string method, NativeArray* arguments); - void jniCallJSCallback(jint callbackId, NativeArray* arguments); + void jniLoadScriptFromAssets( + jni::alias_ref assetManager, + const std::string &assetURL, + bool loadSynchronously); + void jniLoadScriptFromFile( + const std::string &fileName, + const std::string &sourceURL, + bool loadSynchronously); + void jniCallJSFunction( + std::string module, + std::string method, + NativeArray *arguments); + void jniCallJSCallback(jint callbackId, NativeArray *arguments); jni::alias_ref getJSCallInvokerHolder(); - void setGlobalVariable(std::string propName, - std::string&& jsonValue); + void setGlobalVariable(std::string propName, std::string &&jsonValue); jlong getJavaScriptContext(); void handleMemoryPressure(int pressureLevel); @@ -90,4 +103,5 @@ class CatalystInstanceImpl : public jni::HybridClass { std::shared_ptr jsCallInvoker_; }; -}} +} // namespace react +} // namespace facebook diff --git a/ReactAndroid/src/main/jni/react/jni/NativeDeltaClient.cpp b/ReactAndroid/src/main/jni/react/jni/NativeDeltaClient.cpp deleted file mode 100644 index 5a9c007bb24..00000000000 --- a/ReactAndroid/src/main/jni/react/jni/NativeDeltaClient.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. - -// This source code is licensed under the MIT license found in the -// LICENSE file in the root directory of this source tree. - -#include "NativeDeltaClient.h" - -#include -#include -#include - -namespace facebook { -namespace react { - -jni::local_ref NativeDeltaClient::initHybrid( - jni::alias_ref) { - return makeCxxInstance(); -} - -void NativeDeltaClient::registerNatives() { - registerHybrid({ - makeNativeMethod("initHybrid", NativeDeltaClient::initHybrid), - makeNativeMethod("processDelta", NativeDeltaClient::jniProcessDelta), - makeNativeMethod("reset", NativeDeltaClient::jniReset), - }); -} - -void NativeDeltaClient::jniProcessDelta( - jni::alias_ref delta) { - - std::ostringstream deltaMessage; - std::vector buffer(8192); - auto byteBuffer = jni::JByteBuffer::wrapBytes(buffer.data(), buffer.size()); - - size_t pos = 0; - int read = 0; - do { - read = delta->read(byteBuffer); - if (read < 1) { - deltaMessage.write(reinterpret_cast(buffer.data()), pos); - byteBuffer->rewind(); - pos = 0; - } else { - pos += read; - } - } while (read != -1); - - - deltaClient_->patch(folly::parseJson(deltaMessage.str())); -} - -void NativeDeltaClient::jniReset() { - deltaClient_->clear(); -} - -} // namespace react -} // namespace facebook diff --git a/ReactAndroid/src/main/jni/react/jni/NativeDeltaClient.h b/ReactAndroid/src/main/jni/react/jni/NativeDeltaClient.h deleted file mode 100644 index a991e3a2c03..00000000000 --- a/ReactAndroid/src/main/jni/react/jni/NativeDeltaClient.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. - -// This source code is licensed under the MIT license found in the -// LICENSE file in the root directory of this source tree. - -#pragma once - -#include - -#include -#include -#include -#include - -namespace facebook { -namespace react { - -class NativeDeltaClient : public jni::HybridClass { - -public: - static constexpr auto kJavaDescriptor = - "Lcom/facebook/react/bridge/NativeDeltaClient;"; - static jni::local_ref initHybrid(jni::alias_ref); - static void registerNatives(); - - ~NativeDeltaClient() override = default; - - std::shared_ptr getDeltaClient() { - return deltaClient_; - } - -private: - friend HybridBase; - void jniProcessDelta(jni::alias_ref delta); - void jniReset(); - const std::shared_ptr deltaClient_ = - std::make_shared(); -}; - -} // namespace react -} // namespace facebook diff --git a/ReactAndroid/src/main/jni/react/jni/OnLoad.cpp b/ReactAndroid/src/main/jni/react/jni/OnLoad.cpp index c754eb12b16..8c11fb99eb1 100644 --- a/ReactAndroid/src/main/jni/react/jni/OnLoad.cpp +++ b/ReactAndroid/src/main/jni/react/jni/OnLoad.cpp @@ -13,9 +13,8 @@ #include "CatalystInstanceImpl.h" #include "CxxModuleWrapper.h" -#include "JavaScriptExecutorHolder.h" #include "JCallback.h" -#include "NativeDeltaClient.h" +#include "JavaScriptExecutorHolder.h" #include "ProxyExecutor.h" #include "WritableNativeArray.h" #include "WritableNativeMap.h" @@ -32,24 +31,28 @@ namespace react { namespace { struct JavaJSExecutor : public JavaClass { - static constexpr auto kJavaDescriptor = "Lcom/facebook/react/bridge/JavaJSExecutor;"; + static constexpr auto kJavaDescriptor = + "Lcom/facebook/react/bridge/JavaJSExecutor;"; }; -class ProxyJavaScriptExecutorHolder : public HybridClass { +class ProxyJavaScriptExecutorHolder : public HybridClass< + ProxyJavaScriptExecutorHolder, + JavaScriptExecutorHolder> { public: - static constexpr auto kJavaDescriptor = "Lcom/facebook/react/bridge/ProxyJavaScriptExecutor;"; + static constexpr auto kJavaDescriptor = + "Lcom/facebook/react/bridge/ProxyJavaScriptExecutor;"; static local_ref initHybrid( - alias_ref, alias_ref executorInstance) { - return makeCxxInstance( - std::make_shared( + alias_ref, + alias_ref executorInstance) { + return makeCxxInstance(std::make_shared( make_global(executorInstance))); } static void registerNatives() { registerHybrid({ - makeNativeMethod("initHybrid", ProxyJavaScriptExecutorHolder::initHybrid), + makeNativeMethod( + "initHybrid", ProxyJavaScriptExecutorHolder::initHybrid), }); } @@ -58,9 +61,9 @@ class ProxyJavaScriptExecutorHolder : public HybridClass - - + - - This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - */ -package com.facebook.react.devsupport; - -import static org.fest.assertions.api.Assertions.assertThat; - -import com.facebook.react.common.StandardCharsets; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import okio.BufferedSource; -import okio.Okio; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; - -@RunWith(RobolectricTestRunner.class) -public class BundleDeltaClientTest { - private BundleDeltaClient mClient; - - @Rule public TemporaryFolder mFolder = new TemporaryFolder(); - - @Before - public void setUp() { - mClient = BundleDeltaClient.create(BundleDeltaClient.ClientType.DEV_SUPPORT); - } - - @Test - public void testAcceptsSimpleInitialBundle() throws IOException { - File file = mFolder.newFile(); - mClient.processDelta( - bufferedSource( - "{" - + "\"pre\": \"console.log('Hello World!');\"," - + "\"post\": \"console.log('That is all folks!');\"," - + "\"modules\": [[0, \"console.log('Best module.');\"]]" - + "}"), - file); - assertThat(contentOf(file)) - .isEqualTo( - "console.log('Hello World!');\n" - + "console.log('Best module.');\n" - + "console.log('That is all folks!');\n"); - } - - @Test - public void testPatchesInitialBundleWithDeltaBundle() throws IOException { - File file = mFolder.newFile(); - mClient.processDelta( - bufferedSource( - "{" - + "\"pre\": \"pre\"," - + "\"post\": \"post\"," - + "\"modules\": [[0, \"0\"], [1, \"1\"]]" - + "}"), - file); - file = mFolder.newFile(); - mClient.processDelta( - bufferedSource( - "{" - + "\"added\": [[2, \"2\"]]," - + "\"modified\": [[0, \"0.1\"]]," - + "\"deleted\": [1]" - + "}"), - file); - assertThat(contentOf(file)).isEqualTo("pre\n" + "0.1\n" + "2\n" + "post\n"); - } - - @Test - public void testSortsModulesByIdInInitialBundle() throws IOException { - File file = mFolder.newFile(); - mClient.processDelta( - bufferedSource( - "{" - + "\"pre\": \"console.log('Hello World!');\"," - + "\"post\": \"console.log('That is all folks!');\"," - + "\"modules\": [[3, \"3\"], [0, \"0\"], [2, \"2\"], [1, \"1\"]]" - + "}"), - file); - assertThat(contentOf(file)) - .isEqualTo( - "console.log('Hello World!');\n" - + "0\n" - + "1\n" - + "2\n" - + "3\n" - + "console.log('That is all folks!');\n"); - } - - @Test - public void testSortsModulesByIdInPatchedBundle() throws IOException { - File file = mFolder.newFile(); - mClient.processDelta( - bufferedSource( - "{" - + "\"pre\": \"console.log('Hello World!');\"," - + "\"post\": \"console.log('That is all folks!');\"," - + "\"modules\": [[3, \"3\"], [0, \"0\"], [1, \"1\"]]" - + "}"), - file); - file = mFolder.newFile(); - mClient.processDelta( - bufferedSource( - "{" - + "\"added\": [[2, \"2\"]]," - + "\"modified\": [[0, \"0.1\"]]," - + "\"deleted\": [1]" - + "}"), - file); - assertThat(contentOf(file)) - .isEqualTo( - "console.log('Hello World!');\n" - + "0.1\n" - + "2\n" - + "3\n" - + "console.log('That is all folks!');\n"); - } - - private static BufferedSource bufferedSource(String string) { - return Okio.buffer( - Okio.source(new ByteArrayInputStream(string.getBytes(StandardCharsets.UTF_8)))); - } - - private static String contentOf(File file) throws IOException { - return new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8); - } -}