Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions src/utils/editor-environment.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
/**
* Internal dependencies
*/
import { awaitGBKitGlobal, editorLoaded, getGBKit } from './bridge';
import {
awaitGBKitGlobal,
editorLoaded,
getGBKit,
logException,
} from './bridge';
import { configureLocale } from './localization';
import { loadEditorAssets } from './editor-loader';
import { initializeVideoPressAjaxBridge } from './videopress-bridge';
import { initializeFetchInterceptor } from './fetch-interceptor';
import EditorLoadError from '../components/editor-load-error';
import { error } from './logger';
import { setLogLevel, error } from './logger';
import { setUpGlobalErrorHandlers } from './global-error-handler';
import { Platform } from './platform';
import './editor-styles';
Expand All @@ -23,6 +28,7 @@ export async function setUpEditorEnvironment() {
setUpGlobalErrorHandlers();
setBodyClasses();
await awaitGBKitGlobal();
setLogLevelFromGBKit();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hoisted from src/utils/editor.jsx to ensure messages from editor initialization log.

initializeFetchInterceptor();
await configureLocale();
await initializeWordPressGlobals();
Expand Down Expand Up @@ -56,6 +62,18 @@ function setBodyClasses() {
window.document.body.classList.add( ...classNames );
}

/**
* Set the log level based on GBKit configuration.
*
* @return {void}
*/
function setLogLevelFromGBKit() {
const { logLevel } = getGBKit();
if ( logLevel ) {
setLogLevel( logLevel );
}
}

/**
* Initialize WordPress global modules. Lazy-loaded to ensure the locale is
* configured before importing these modules and referencing the corresponding
Expand Down Expand Up @@ -100,7 +118,11 @@ async function loadPluginsIfEnabled() {
try {
const { allowedBlockTypes } = await loadEditorAssets();
return { allowedBlockTypes, pluginLoadFailed: false };
} catch {
} catch ( err ) {
logException( err, {
isHandled: true,
handledBy: 'loadPluginsIfEnabled',
} );
Comment on lines +122 to +125
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improve observability of plugin loading failures.

return { pluginLoadFailed: true };
}
}
Expand Down Expand Up @@ -129,6 +151,10 @@ async function initializeEditor( pluginLoadResult = {} ) {
* @param {Error} err - The error that occurred
*/
function handleError( err ) {
logException( err, {
isHandled: true,
handledBy: 'setUpEditorEnvironment',
} );
Comment on lines +154 to +157
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improve observability of editor initialization failures.

error( 'Error initializing editor', err );
const errorDetails = EditorLoadError( { error: err } );
document.body.innerHTML = errorDetails;
Expand Down
41 changes: 40 additions & 1 deletion src/utils/editor-environment.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ import { describe, it, expect, vi, beforeEach } from 'vitest';
* Internal dependencies
*/
import { setUpEditorEnvironment } from './editor-environment';
import { awaitGBKitGlobal, getGBKit, editorLoaded } from './bridge.js';
import {
awaitGBKitGlobal,
getGBKit,
editorLoaded,
logException,
} from './bridge.js';
import { loadEditorAssets } from './editor-loader.js';
import EditorLoadError from '../components/editor-load-error/index.jsx';
import { error } from './logger.js';
Expand Down Expand Up @@ -147,6 +152,10 @@ describe( 'setUpEditorEnvironment', () => {

await setUpEditorEnvironment();

expect( logException ).toHaveBeenCalledWith( testError, {
isHandled: true,
handledBy: 'setUpEditorEnvironment',
} );
expect( error ).toHaveBeenCalledWith(
'Error initializing editor',
testError
Expand All @@ -164,6 +173,10 @@ describe( 'setUpEditorEnvironment', () => {

await setUpEditorEnvironment();

expect( logException ).toHaveBeenCalledWith( testError, {
isHandled: true,
handledBy: 'setUpEditorEnvironment',
} );
expect( error ).toHaveBeenCalledWith(
'Error initializing editor',
testError
Expand All @@ -179,6 +192,10 @@ describe( 'setUpEditorEnvironment', () => {

await setUpEditorEnvironment();

expect( logException ).toHaveBeenCalledWith( testError, {
isHandled: true,
handledBy: 'setUpEditorEnvironment',
} );
expect( error ).toHaveBeenCalledWith(
'Error initializing editor',
testError
Expand All @@ -196,6 +213,10 @@ describe( 'setUpEditorEnvironment', () => {

await setUpEditorEnvironment();

expect( logException ).toHaveBeenCalledWith( testError, {
isHandled: true,
handledBy: 'setUpEditorEnvironment',
} );
expect( error ).toHaveBeenCalledWith(
'Error initializing editor',
testError
Expand All @@ -209,4 +230,22 @@ describe( 'setUpEditorEnvironment', () => {
expect( result ).toBeInstanceOf( Promise );
await expect( result ).resolves.toBeUndefined();
} );

it( 'logs exception when plugin loading fails', async () => {
getGBKit.mockReturnValue( { plugins: true } );

const testError = new Error( 'Asset loading failed' );
loadEditorAssets.mockRejectedValue( testError );

await setUpEditorEnvironment();

expect( logException ).toHaveBeenCalledWith( testError, {
isHandled: true,
handledBy: 'loadPluginsIfEnabled',
} );
expect( initializeEditor ).toHaveBeenCalledWith( {
allowedBlockTypes: undefined,
pluginLoadFailed: true,
} );
} );
} );
10 changes: 1 addition & 9 deletions src/utils/editor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { registerCoreBlocks } from '@wordpress/block-library';
import { unregisterDisallowedBlocks } from './blocks';
import { getGBKit, getPost } from './bridge';
import { getDefaultEditorSettings } from './editor-settings';
import { setLogLevel, LOG_LEVELS } from './logger';

/**
* Configure editor settings and styles, and render the editor.
Expand All @@ -23,12 +22,7 @@ export function initializeEditor( {
allowedBlockTypes,
pluginLoadFailed,
} = {} ) {
const {
themeStyles,
hideTitle,
editorSettings,
logLevel = LOG_LEVELS.INFO,
} = getGBKit();
const { themeStyles, hideTitle, editorSettings } = getGBKit();

const settings = editorSettings || getDefaultEditorSettings();
dispatch( editorStore ).updateEditorSettings( settings );
Expand All @@ -41,8 +35,6 @@ export function initializeEditor( {
themeStyles,
} );

setLogLevel( logLevel );

// Force visual mode on initialization to ensure consistency with native UI,
// which defaults to visual mode. In the future, we could allow the native
// host app to configure the initial editor mode.
Expand Down
5 changes: 1 addition & 4 deletions src/utils/exception-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,7 @@ const parseException = ( originalException ) => {
message: extractMessage( originalException ),
};

const stacktrace = parseStacktrace( originalException );
if ( stacktrace.length ) {
exception.stacktrace = stacktrace;
}
exception.stacktrace = parseStacktrace( originalException );
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Always set the stacktrace to avoid native hosts discarding logged exceptions—e.g., ios/Sources/GutenbergKit/Sources/EditorViewControllerDelegate.swift.

E.g., if fetchEditorAssets throws due to an error from the native host, the error object will have an empty stack trace in the JavaScript runtime.


if ( exception.type === undefined && exception.message === '' ) {
exception.message = 'Unknown error';
Expand Down