diff --git a/.buildkite/commands/publish-react-native-bridge-android-artifacts.sh b/.buildkite/commands/publish-react-native-bridge-android-artifacts.sh index 80fdd14497..c771bc6836 100755 --- a/.buildkite/commands/publish-react-native-bridge-android-artifacts.sh +++ b/.buildkite/commands/publish-react-native-bridge-android-artifacts.sh @@ -5,11 +5,13 @@ set -euo pipefail # Retrieve data from previous steps PUBLISHED_AZTEC_VERSION=`buildkite-agent meta-data get "PUBLISHED_REACT_NATIVE_AZTEC_ANDROID_VERSION"` buildkite-agent artifact download bundle/android/App.js . +buildkite-agent artifact download bundle/android/App.composed.js.map . # Copy the JavaScript bundle and all local static assets referenced within the # bundle to the appropriate locations for inclusion in the bridge bundle mkdir -p gutenberg/packages/react-native-bridge/android/react-native-bridge/build/assets cp ./bundle/android/App.js ./gutenberg/packages/react-native-bridge/android/react-native-bridge/build/assets/index.android.bundle +cp ./bundle/android/App.composed.js.map ./gutenberg/packages/react-native-bridge/android/react-native-bridge/build/assets/index.android.bundle.map cp -r ./bundle/android/drawable-* ./gutenberg/packages/react-native-bridge/android/react-native-bridge/src/main/res/ # Publish react-native-bridge diff --git a/.buildkite/commands/publish-react-native-ios-artifacts.sh b/.buildkite/commands/publish-react-native-ios-artifacts.sh index d9dbb8a241..5a677b5f42 100755 --- a/.buildkite/commands/publish-react-native-ios-artifacts.sh +++ b/.buildkite/commands/publish-react-native-ios-artifacts.sh @@ -2,6 +2,7 @@ echo "--- :arrow_down: Download iOS JS bundle" buildkite-agent artifact download bundle/ios/App.js . +buildkite-agent artifact download bundle/ios/App.composed.js.map . buildkite-agent artifact download ios-assets.tar.gz . mkdir -p ios-xcframework/Gutenberg/Resources tar -xzvf ios-assets.tar.gz -C ios-xcframework/Gutenberg/Resources/ diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index ec2aa17ec3..66ea21eeec 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -143,29 +143,19 @@ steps: echo "--- :android: Build Android bundle" npm run bundle:android - echo "--- :arrow_up: Upload Android bundle artifact" + echo "--- :arrow_up: Upload Android bundle and source map artifacts" buildkite-agent artifact upload bundle/android/App.js - - if [[ -n "$BUILDKITE_TAG" ]]; then - echo "--- :arrow_up: Upload Android source map" - node gutenberg/node_modules/react-native/scripts/compose-source-maps.js bundle/android/App.text.js.map bundle/android/App.js.map -o bundle/android/App.composed.js.map - buildkite-agent artifact upload bundle/android/App.composed.js.map - fi + buildkite-agent artifact upload bundle/android/App.composed.js.map echo "--- :ios: Build iOS bundle" npm run bundle:ios - echo "--- :arrow_up: Upload iOS bundle artifact" + echo "--- :arrow_up: Upload iOS bundle and source map artifacts" buildkite-agent artifact upload bundle/ios/App.js + buildkite-agent artifact upload bundle/ios/App.composed.js.map tar -czvf ios-assets.tar.gz -C ios-xcframework/Gutenberg/Resources assets/ buildkite-agent artifact upload ios-assets.tar.gz - if [[ -n "$BUILDKITE_TAG" ]]; then - echo "--- :arrow_up: Upload iOS source map" - node gutenberg/node_modules/react-native/scripts/compose-source-maps.js bundle/ios/App.text.js.map bundle/ios/App.js.map -o bundle/ios/App.composed.js.map - buildkite-agent artifact upload bundle/ios/App.composed.js.map - fi - - label: "Build Android RN Aztec & Publish to S3" depends_on: - lint diff --git a/.gitignore b/.gitignore index a4f0ea5172..b430ab05bd 100644 --- a/.gitignore +++ b/.gitignore @@ -40,10 +40,7 @@ gen/ build/ build.log bundle/android/raw/* -bundle/android/App.js -bundle/android/App.js.map -bundle/android/App.text.js -bundle/android/App.text.js.map +bundle/android/App.* bundle/ios/App.* bundle/ios/assets/gutenberg/packages/block-library/src/* diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 557f42492d..845e0221ad 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -1,6 +1,7 @@ Unreleased --- * [**] [internal] Upgrade React Native to version 0.73.3 [https://github.com/wordpress-mobile/gutenberg-mobile/pull/6590] +* [**] Add error boundary components and exception logging [https://github.com/wordpress-mobile/gutenberg-mobile/pull/6655] 1.114.0 --- diff --git a/gutenberg b/gutenberg index 272f402871..ef63dcc089 160000 --- a/gutenberg +++ b/gutenberg @@ -1 +1 @@ -Subproject commit 272f4028718fadf56522f5ccf55ffa72049026bb +Subproject commit ef63dcc0890dbea12e61f4e2cde55c04614eeb4a diff --git a/ios-xcframework/XCFrameworkScaffold.xcodeproj/project.pbxproj b/ios-xcframework/XCFrameworkScaffold.xcodeproj/project.pbxproj index 83e6fa0a98..835638a842 100644 --- a/ios-xcframework/XCFrameworkScaffold.xcodeproj/project.pbxproj +++ b/ios-xcframework/XCFrameworkScaffold.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 1D9EA4BE2B87A2570086B30F /* App.composed.js.map in Resources */ = {isa = PBXBuildFile; fileRef = 1D9EA4BD2B87A2470086B30F /* App.composed.js.map */; }; 2F4F38292B86842C006EF573 /* external-style-overrides.css in Resources */ = {isa = PBXBuildFile; fileRef = 2F4F38282B86842C006EF573 /* external-style-overrides.css */; }; 2F4F382B2B86844A006EF573 /* extra-localstorage-entries.js in Resources */ = {isa = PBXBuildFile; fileRef = 2F4F382A2B86844A006EF573 /* extra-localstorage-entries.js */; }; 2F4F382D2B868457006EF573 /* remove-nux.js in Resources */ = {isa = PBXBuildFile; fileRef = 2F4F382C2B868457006EF573 /* remove-nux.js */; }; @@ -41,6 +42,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 1D9EA4BD2B87A2470086B30F /* App.composed.js.map */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; name = App.composed.js.map; path = ../../../bundle/ios/App.composed.js.map; sourceTree = ""; }; 2F4F38282B86842C006EF573 /* external-style-overrides.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = "external-style-overrides.css"; path = "../../../resources/unsupported-block-editor/external-style-overrides.css"; sourceTree = ""; }; 2F4F382A2B86844A006EF573 /* extra-localstorage-entries.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = "extra-localstorage-entries.js"; path = "../../../resources/unsupported-block-editor/extra-localstorage-entries.js"; sourceTree = ""; }; 2F4F382C2B868457006EF573 /* remove-nux.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = "remove-nux.js"; path = "../../../resources/unsupported-block-editor/remove-nux.js"; sourceTree = ""; }; @@ -96,6 +98,7 @@ 2F4F382A2B86844A006EF573 /* extra-localstorage-entries.js */, 2F4F38282B86842C006EF573 /* external-style-overrides.css */, 3FA0C5802A1C8C9700600A9A /* App.js */, + 1D9EA4BD2B87A2470086B30F /* App.composed.js.map */, 3F12363F29F6B21300AF54A4 /* content-functions.js */, 3F12364429F6B21300AF54A4 /* editor-behavior-overrides.js */, 3F12363D29F6B21300AF54A4 /* editor-style-overrides.css */, @@ -269,6 +272,7 @@ 3F12364C29F6B21300AF54A4 /* wp-bar-override.css in Resources */, 3F12365029F6B23300AF54A4 /* supported-blocks.json in Resources */, 3FA0C5812A1C8C9700600A9A /* App.js in Resources */, + 1D9EA4BE2B87A2570086B30F /* App.composed.js.map in Resources */, 2F4F38292B86842C006EF573 /* external-style-overrides.css in Resources */, 3F12364729F6B21300AF54A4 /* insert-block.js in Resources */, ); diff --git a/package.json b/package.json index d711e759da..2b2f493a5e 100644 --- a/package.json +++ b/package.json @@ -71,10 +71,10 @@ "bundle": "npm run clean && npm run bundle:js", "prebundle:js": "npm run i18n:update", "bundle:js": "npm run bundle:android && npm run bundle:ios", - "bundle:android": "npm run bundle:android:text && npm run bundle:android:bytecode", + "bundle:android": "npm run bundle:android:text && npm run bundle:android:bytecode && node gutenberg/node_modules/react-native/scripts/compose-source-maps.js bundle/android/App.text.js.map bundle/android/App.js.map -o bundle/android/App.composed.js.map", "bundle:android:text": "mkdir -p bundle/android && npm run rn-bundle -- -- -- -- --config ../../../metro.config.js --platform android --dev false --entry-file ./index.js --assets-dest ../../../bundle/android --bundle-output ../../../bundle/android/App.text.js --sourcemap-output ../../../bundle/android/App.text.js.map", "bundle:android:bytecode": "./gutenberg/node_modules/react-native/sdks/hermesc/`node -e \"const platform=require('os').platform();console.log(platform === 'darwin' ? 'osx-bin' : (platform === 'linux' ? 'linux64-bin' : (platform === 'win32' ? 'win64-bin' : 'unsupported-os')));\"`/hermesc -emit-binary -O -out bundle/android/App.js bundle/android/App.text.js -output-source-map", - "bundle:ios": "npm run bundle:ios:text && npm run bundle:ios:bytecode", + "bundle:ios": "npm run bundle:ios:text && npm run bundle:ios:bytecode && node gutenberg/node_modules/react-native/scripts/compose-source-maps.js bundle/ios/App.text.js.map bundle/ios/App.js.map -o bundle/ios/App.composed.js.map", "bundle:ios:text": "mkdir -p bundle/ios && npm run rn-bundle -- -- -- -- --config ../../../metro.config.js --platform ios --dev false --entry-file ./index.js --assets-dest ../../../ios-xcframework/Gutenberg/Resources --bundle-output ../../../bundle/ios/App.text.js --sourcemap-output ../../../bundle/ios/App.text.js.map", "bundle:ios:bytecode": "./gutenberg/node_modules/react-native/sdks/hermesc/`node -e \"const platform=require('os').platform();console.log(platform === 'darwin' ? 'osx-bin' : (platform === 'linux' ? 'linux64-bin' : (platform === 'win32' ? 'win64-bin' : 'unsupported-os')));\"`/hermesc -emit-binary -O -out bundle/ios/App.js bundle/ios/App.text.js -output-source-map", "prewpandroid": "rm -Rf $TMPDIR/gbmobile-wpandroidfakernroot && mkdir $TMPDIR/gbmobile-wpandroidfakernroot && ln -s $(cd \"$(dirname \"../../../\")\"; pwd) $TMPDIR/gbmobile-wpandroidfakernroot/android", diff --git a/src/errorLogging/index.js b/src/errorLogging/index.js new file mode 100644 index 0000000000..e069b39bdb --- /dev/null +++ b/src/errorLogging/index.js @@ -0,0 +1,44 @@ +/** + * WordPress dependencies + */ +import { logException } from '@wordpress/react-native-bridge'; + +// Setting Error handler to send exceptions. This implementation is based on Sentry React Native SDK: +// https://github.com/getsentry/sentry-react-native/blob/adfb66f16438dfd98f280307844778c7291b584b/src/js/integrations/reactnativeerrorhandlers.ts#L187-L262 +export default () => { + const errorUtils = global.ErrorUtils; + const defaultHandler = + errorUtils.getGlobalHandler && errorUtils.getGlobalHandler(); + + let handlingFatal = false; + errorUtils.setGlobalHandler( ( error, isFatal ) => { + // For now, only fatal errors are logged + if ( ! isFatal ) { + defaultHandler( error, isFatal ); + return; + } + + // On production, we only allow logging a single fatal error. + // This prevents sending extra exceptions derived from the original error. + if ( ! __DEV__ ) { + if ( handlingFatal ) { + // eslint-disable-next-line no-console + console.warn( + 'Encountered multiple fatals in a row. The latest:', + error + ); + return; + } + handlingFatal = true; + } + + logException( + error, + { isHandled: false, handledBy: 'Global Error Handler' }, + () => { + // Wait for the exception to be sent to host app + defaultHandler( error, isFatal ); + } + ); + } ); +}; diff --git a/src/setup.js b/src/setup.js index c5ecd6d20a..03dab19417 100644 --- a/src/setup.js +++ b/src/setup.js @@ -9,6 +9,7 @@ import { initialHtmlGutenberg } from '@wordpress/react-native-editor'; */ import initialHtml from './initial-html'; import initAnalytics from './analytics'; +import initErrorLogging from './errorLogging'; const setupHooks = () => { // Hook triggered before the editor is rendered @@ -75,4 +76,5 @@ const setupHooks = () => { export default () => { initAnalytics(); setupHooks(); + initErrorLogging(); };