From ab43358da77dd562b5bccf231a1a15434897be97 Mon Sep 17 00:00:00 2001 From: Kevin Gozali Date: Tue, 3 May 2022 18:11:35 -0700 Subject: [PATCH] iOS: Introduced ReactNativeRuntimeDiagnostics for various runtime validation mechanism Summary: With the new architecture, this diagnostic utility will be helpful to ensure stronger validation of various corner cases at runtime, like handling an early JavaScript exception when loading React Native. If `global.RN$DiagnosticFlags` is set to a string of comma-separated flags, the util functions will be able to perform additional diagnostics. For now, the accepted flags are: - `early_js_errors` - `all` This is still experimental and may change frequently. Changelog: [Internal] Reviewed By: RSNara Differential Revision: D36088407 fbshipit-source-id: 9059d2d081b0f41d049310fb09650416b333ff57 --- .../ReactNativeRuntimeDiagnostics.js | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 Libraries/ReactNative/ReactNativeRuntimeDiagnostics.js diff --git a/Libraries/ReactNative/ReactNativeRuntimeDiagnostics.js b/Libraries/ReactNative/ReactNativeRuntimeDiagnostics.js new file mode 100644 index 00000000000..82bea13749c --- /dev/null +++ b/Libraries/ReactNative/ReactNativeRuntimeDiagnostics.js @@ -0,0 +1,68 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +'use strict'; + +/** + * Perform a set of runtime diagnostics, usually useful for test purpose. + * This is only meaningful for __DEV__ mode. + */ +export type RuntimeDiagnostics = {| + /** + * Check if the runtime diagnostics is enabled at all. + */ + isEnabled: () => boolean, + + /** + * If enabled, simulate early JavaScript errors during initialization. + */ + simulateEarlyJavaScriptErrors: () => void, +|}; + +export type RuntimeDiagnosticFlag = 'early_js_errors' | 'all'; + +const flags: Array = []; +let isEnabled = false; +let shouldEnableAll = false; + +if (__DEV__) { + if (typeof global.RN$DiagnosticFlags === 'string') { + global.RN$DiagnosticFlags.split(',').forEach(flag => { + switch (flag) { + case 'early_js_errors': + case 'all': + flags.push(flag); + break; + default: + throw Error( + `RuntimeDiagnosticsFlags: unknown flag was supplied: '${flag}'`, + ); + } + }); + isEnabled = flags.length > 0; + shouldEnableAll = flags.includes('all'); + } +} + +const ReactNativeRuntimeDiagnostics: RuntimeDiagnostics = { + isEnabled: () => isEnabled, + simulateEarlyJavaScriptErrors: () => { + if (__DEV__) { + if (!isEnabled) { + return; + } + if (shouldEnableAll || flags.includes('early_js_errors')) { + throw Error('[Runtime Diagnostics] Throwing a JavaScript error.'); + } + } + }, +}; + +module.exports = ReactNativeRuntimeDiagnostics;