From 6057b1d418f28908537d4e0807fb314b78cf3e8e Mon Sep 17 00:00:00 2001 From: LinXunFeng Date: Wed, 6 Mar 2024 11:49:59 +0800 Subject: [PATCH 01/11] Fixs JSON.stringify() cannot serialize cyclic structures --- .../webview_flutter_test.dart | 45 +++++++++++++++++++ .../lib/src/webkit_webview_controller.dart | 25 ++++++++++- .../test/webkit_webview_controller_test.dart | 19 +++++++- 3 files changed, 87 insertions(+), 2 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart index 91d9075cd47..a07b94d5bc2 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart @@ -1447,6 +1447,51 @@ Future main() async { await expectLater( debugMessageReceived.future, completion('debug:Debug message')); }); + + testWidgets('can receive console log messages with cyclic object value', + (WidgetTester tester) async { + const String testPage = ''' + + + + WebResourceError test + + + + + '''; + + final Completer debugMessageReceived = Completer(); + final PlatformWebViewController controller = PlatformWebViewController( + const PlatformWebViewControllerCreationParams(), + ); + unawaited(controller.setJavaScriptMode(JavaScriptMode.unrestricted)); + + await controller + .setOnConsoleMessage((JavaScriptConsoleMessage consoleMessage) { + debugMessageReceived + .complete('${consoleMessage.level.name}:${consoleMessage.message}'); + }); + + await controller.loadHtmlString(testPage); + + await tester.pumpWidget(Builder( + builder: (BuildContext context) { + return PlatformWebViewWidget( + PlatformWebViewWidgetCreationParams(controller: controller), + ).build(context); + }, + )); + + await expectLater(debugMessageReceived.future, + completion('log:{"otherData":123,"myself":"[Circular]"}')); + }); }); } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart index c4e38230de8..44c7f59b115 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart @@ -630,11 +630,34 @@ class WebKitWebViewController extends PlatformWebViewController { } Future _injectConsoleOverride() { + // Using the replacer parameter of JSON.stringify() to solve the error + // TypeError: JSON.stringify cannot serialize cyclic structures. + // See https://github.com/flutter/flutter/issues/144535. + // + // The getCircularReplacer() taken from + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value. const WKUserScript overrideScript = WKUserScript( ''' +function getCircularReplacer() { + const ancestors = []; + return function (key, value) { + if (typeof value !== "object" || value === null) { + return value; + } + while (ancestors.length > 0 && ancestors.at(-1) !== this) { + ancestors.pop(); + } + if (ancestors.includes(value)) { + return "[Circular]"; + } + ancestors.push(value); + return value; + }; +} + function log(type, args) { var message = Object.values(args) - .map(v => typeof(v) === "undefined" ? "undefined" : typeof(v) === "object" ? JSON.stringify(v) : v.toString()) + .map(v => typeof(v) === "undefined" ? "undefined" : typeof(v) === "object" ? JSON.stringify(v, getCircularReplacer()) : v.toString()) .map(v => v.substring(0, 3000)) // Limit msg to 3000 chars .join(", "); diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart index a23eef8d8fb..525519bf703 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart @@ -1378,9 +1378,26 @@ void main() { expect(overrideConsoleScript.injectionTime, WKUserScriptInjectionTime.atDocumentStart); expect(overrideConsoleScript.source, ''' +function getCircularReplacer() { + const ancestors = []; + return function (key, value) { + if (typeof value !== "object" || value === null) { + return value; + } + while (ancestors.length > 0 && ancestors.at(-1) !== this) { + ancestors.pop(); + } + if (ancestors.includes(value)) { + return "[Circular]"; + } + ancestors.push(value); + return value; + }; +} + function log(type, args) { var message = Object.values(args) - .map(v => typeof(v) === "undefined" ? "undefined" : typeof(v) === "object" ? JSON.stringify(v) : v.toString()) + .map(v => typeof(v) === "undefined" ? "undefined" : typeof(v) === "object" ? JSON.stringify(v, getCircularReplacer()) : v.toString()) .map(v => v.substring(0, 3000)) // Limit msg to 3000 chars .join(", "); From a37f7bfd9f703cb4adbce93c84c4eac5c467a99b Mon Sep 17 00:00:00 2001 From: LinXunFeng Date: Wed, 6 Mar 2024 12:39:26 +0800 Subject: [PATCH 02/11] Update version and CHANGELOG --- .../webview_flutter/webview_flutter_wkwebview/CHANGELOG.md | 4 ++++ .../webview_flutter/webview_flutter_wkwebview/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md index 8aa73ace026..aa9df31080d 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.12.1 + +* Fixes `JSON.stringify()` cannot serialize cyclic structures. + ## 3.12.0 * Adds support for `setOnScrollPositionChange` method to the `WebKitWebViewController`. diff --git a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml index 18a0cef72e8..c64c316b307 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml @@ -2,7 +2,7 @@ name: webview_flutter_wkwebview description: A Flutter plugin that provides a WebView widget based on Apple's WKWebView control. repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_wkwebview issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22 -version: 3.12.0 +version: 3.12.1 environment: sdk: ^3.2.3 From 182afac743fe51d6dfbb97bc13bb5ff0037a138b Mon Sep 17 00:00:00 2001 From: LinXunFeng Date: Tue, 12 Mar 2024 18:48:16 +0800 Subject: [PATCH 03/11] Remove cyclic object --- .../webview_flutter_test.dart | 12 +++++--- .../lib/src/webkit_webview_controller.dart | 29 +++++++------------ .../test/webkit_webview_controller_test.dart | 23 +++++---------- 3 files changed, 27 insertions(+), 37 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart index a07b94d5bc2..90960543ef8 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart @@ -1457,9 +1457,13 @@ Future main() async { WebResourceError test @@ -1490,7 +1494,7 @@ Future main() async { )); await expectLater(debugMessageReceived.future, - completion('log:{"otherData":123,"myself":"[Circular]"}')); + completion('log:{"a":"Flutter","b":{}}')); }); }); } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart index 44c7f59b115..c204f68fd54 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart @@ -633,31 +633,24 @@ class WebKitWebViewController extends PlatformWebViewController { // Using the replacer parameter of JSON.stringify() to solve the error // TypeError: JSON.stringify cannot serialize cyclic structures. // See https://github.com/flutter/flutter/issues/144535. - // - // The getCircularReplacer() taken from - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value. + // + // Considering this is just looking at the logs printed via console.log, + // the cyclic object is not important, so remove it. const WKUserScript overrideScript = WKUserScript( ''' -function getCircularReplacer() { - const ancestors = []; - return function (key, value) { - if (typeof value !== "object" || value === null) { - return value; - } - while (ancestors.length > 0 && ancestors.at(-1) !== this) { - ancestors.pop(); - } - if (ancestors.includes(value)) { - return "[Circular]"; - } - ancestors.push(value); - return value; +function removeCyclicObject() { + const objects = new WeakSet(); + return function (k, v) { + if (typeof v !== "object" || v === null) { return v; } + if (objects.has(v)) { return; } + objects.add(v); + return v; }; } function log(type, args) { var message = Object.values(args) - .map(v => typeof(v) === "undefined" ? "undefined" : typeof(v) === "object" ? JSON.stringify(v, getCircularReplacer()) : v.toString()) + .map(v => typeof(v) === "undefined" ? "undefined" : typeof(v) === "object" ? JSON.stringify(v, removeCyclicObject()) : v.toString()) .map(v => v.substring(0, 3000)) // Limit msg to 3000 chars .join(", "); diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart index 525519bf703..dd14a472845 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart @@ -1378,26 +1378,19 @@ void main() { expect(overrideConsoleScript.injectionTime, WKUserScriptInjectionTime.atDocumentStart); expect(overrideConsoleScript.source, ''' -function getCircularReplacer() { - const ancestors = []; - return function (key, value) { - if (typeof value !== "object" || value === null) { - return value; - } - while (ancestors.length > 0 && ancestors.at(-1) !== this) { - ancestors.pop(); - } - if (ancestors.includes(value)) { - return "[Circular]"; - } - ancestors.push(value); - return value; +function removeCyclicObject() { + const objects = new WeakSet(); + return function (k, v) { + if (typeof v !== "object" || v === null) { return v; } + if (objects.has(v)) { return; } + objects.add(v); + return v; }; } function log(type, args) { var message = Object.values(args) - .map(v => typeof(v) === "undefined" ? "undefined" : typeof(v) === "object" ? JSON.stringify(v, getCircularReplacer()) : v.toString()) + .map(v => typeof(v) === "undefined" ? "undefined" : typeof(v) === "object" ? JSON.stringify(v, removeCyclicObject()) : v.toString()) .map(v => v.substring(0, 3000)) // Limit msg to 3000 chars .join(", "); From ee66a4a13b28eba4eaad8d9191644cca975b8cdd Mon Sep 17 00:00:00 2001 From: LinXunFeng Date: Tue, 12 Mar 2024 18:56:55 +0800 Subject: [PATCH 04/11] Remove whitespace --- .../lib/src/webkit_webview_controller.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart index c204f68fd54..30b766dee79 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart @@ -634,7 +634,7 @@ class WebKitWebViewController extends PlatformWebViewController { // TypeError: JSON.stringify cannot serialize cyclic structures. // See https://github.com/flutter/flutter/issues/144535. // - // Considering this is just looking at the logs printed via console.log, + // Considering this is just looking at the logs printed via console.log, // the cyclic object is not important, so remove it. const WKUserScript overrideScript = WKUserScript( ''' From a709175bc7a0cdfbe85e09eaf6bf27942141a7ca Mon Sep 17 00:00:00 2001 From: LinXunFeng Date: Tue, 12 Mar 2024 19:04:09 +0800 Subject: [PATCH 05/11] Remove whitespace --- .../lib/src/webkit_webview_controller.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart index 30b766dee79..7832f13d1c4 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart @@ -633,7 +633,7 @@ class WebKitWebViewController extends PlatformWebViewController { // Using the replacer parameter of JSON.stringify() to solve the error // TypeError: JSON.stringify cannot serialize cyclic structures. // See https://github.com/flutter/flutter/issues/144535. - // + // // Considering this is just looking at the logs printed via console.log, // the cyclic object is not important, so remove it. const WKUserScript overrideScript = WKUserScript( From b7a366182b0b443875b4b1cda9a0afc40e18e6f7 Mon Sep 17 00:00:00 2001 From: LinXunFeng Date: Fri, 15 Mar 2024 18:10:15 +0800 Subject: [PATCH 06/11] Improve logic --- .../webview_flutter_test.dart | 19 ++++++++++++++----- .../lib/src/webkit_webview_controller.dart | 13 ++++++++++--- .../test/webkit_webview_controller_test.dart | 13 ++++++++++--- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart index 90960543ef8..68f9c8e0ad6 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart @@ -1457,12 +1457,18 @@ Future main() async { WebResourceError test @@ -1493,8 +1499,11 @@ Future main() async { }, )); - await expectLater(debugMessageReceived.future, - completion('log:{"a":"Flutter","b":{}}')); + await expectLater( + debugMessageReceived.future, + completion( + 'log:{"obj1":{"name":"obj1"},"obj2":{"name":"obj2","obj1":{"name":"obj1"}}}'), + ); }); }); } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart index 7832f13d1c4..87ada28ce21 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart @@ -639,11 +639,18 @@ class WebKitWebViewController extends PlatformWebViewController { const WKUserScript overrideScript = WKUserScript( ''' function removeCyclicObject() { - const objects = new WeakSet(); + const levelObjects = []; return function (k, v) { if (typeof v !== "object" || v === null) { return v; } - if (objects.has(v)) { return; } - objects.add(v); + const currentParentObj = this; + while ( + levelObjects.length > 0 && + levelObjects[levelObjects.length - 1] !== currentParentObj + ) { + levelObjects.pop(); + } + if (levelObjects.includes(v)) { return; } + levelObjects.push(v); return v; }; } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart index dd14a472845..e37f40ace05 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart @@ -1379,11 +1379,18 @@ void main() { WKUserScriptInjectionTime.atDocumentStart); expect(overrideConsoleScript.source, ''' function removeCyclicObject() { - const objects = new WeakSet(); + const levelObjects = []; return function (k, v) { if (typeof v !== "object" || v === null) { return v; } - if (objects.has(v)) { return; } - objects.add(v); + const currentParentObj = this; + while ( + levelObjects.length > 0 && + levelObjects[levelObjects.length - 1] !== currentParentObj + ) { + levelObjects.pop(); + } + if (levelObjects.includes(v)) { return; } + levelObjects.push(v); return v; }; } From ae1a4a2a4f46559eb3f13a2f6cdef8d2341b6b02 Mon Sep 17 00:00:00 2001 From: LinXunFeng Date: Tue, 30 Apr 2024 09:07:09 +0800 Subject: [PATCH 07/11] Adjust to use _flutter_webview_plugin_overrides namespace --- .../lib/src/webkit_webview_controller.dart | 71 ++++++++++--------- .../test/webkit_webview_controller_test.dart | 71 ++++++++++--------- 2 files changed, 72 insertions(+), 70 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart index d3e5b588b63..bbf38c1c3e3 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart @@ -638,36 +638,37 @@ class WebKitWebViewController extends PlatformWebViewController { // the cyclic object is not important, so remove it. const WKUserScript overrideScript = WKUserScript( ''' -function removeCyclicObject() { - const levelObjects = []; - return function (k, v) { - if (typeof v !== "object" || v === null) { return v; } - const currentParentObj = this; - while ( - levelObjects.length > 0 && - levelObjects[levelObjects.length - 1] !== currentParentObj - ) { - levelObjects.pop(); - } - if (levelObjects.includes(v)) { return; } - levelObjects.push(v); - return v; - }; -} - -function log(type, args) { - var message = Object.values(args) - .map(v => typeof(v) === "undefined" ? "undefined" : typeof(v) === "object" ? JSON.stringify(v, removeCyclicObject()) : v.toString()) - .map(v => v.substring(0, 3000)) // Limit msg to 3000 chars - .join(", "); - - var log = { - level: type, - message: message - }; - - window.webkit.messageHandlers.fltConsoleMessage.postMessage(JSON.stringify(log)); -} +var _flutter_webview_plugin_overrides = _flutter_webview_plugin_overrides || { + removeCyclicObject: function() { + const levelObjects = []; + return function (k, v) { + if (typeof v !== "object" || v === null) { return v; } + const currentParentObj = this; + while ( + levelObjects.length > 0 && + levelObjects[levelObjects.length - 1] !== currentParentObj + ) { + levelObjects.pop(); + } + if (levelObjects.includes(v)) { return; } + levelObjects.push(v); + return v; + }; + }, + log: function (type, args) { + var message = Object.values(args) + .map(v => typeof(v) === "undefined" ? "undefined" : typeof(v) === "object" ? JSON.stringify(v, _flutter_webview_plugin_overrides.removeCyclicObject()) : v.toString()) + .map(v => v.substring(0, 3000)) // Limit msg to 3000 chars + .join(", "); + + var log = { + level: type, + message: message + }; + + window.webkit.messageHandlers.fltConsoleMessage.postMessage(JSON.stringify(log)); + } +}; let originalLog = console.log; let originalInfo = console.info; @@ -675,11 +676,11 @@ let originalWarn = console.warn; let originalError = console.error; let originalDebug = console.debug; -console.log = function() { log("log", arguments); originalLog.apply(null, arguments) }; -console.info = function() { log("info", arguments); originalInfo.apply(null, arguments) }; -console.warn = function() { log("warning", arguments); originalWarn.apply(null, arguments) }; -console.error = function() { log("error", arguments); originalError.apply(null, arguments) }; -console.debug = function() { log("debug", arguments); originalDebug.apply(null, arguments) }; +console.log = function() { _flutter_webview_plugin_overrides.log("log", arguments); originalLog.apply(null, arguments) }; +console.info = function() { _flutter_webview_plugin_overrides.log("info", arguments); originalInfo.apply(null, arguments) }; +console.warn = function() { _flutter_webview_plugin_overrides.log("warning", arguments); originalWarn.apply(null, arguments) }; +console.error = function() { _flutter_webview_plugin_overrides.log("error", arguments); originalError.apply(null, arguments) }; +console.debug = function() { _flutter_webview_plugin_overrides.log("debug", arguments); originalDebug.apply(null, arguments) }; window.addEventListener("error", function(e) { log("error", e.message + " at " + e.filename + ":" + e.lineno + ":" + e.colno); diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart index f56462b4bc3..c63b034f585 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart @@ -1378,36 +1378,37 @@ void main() { expect(overrideConsoleScript.injectionTime, WKUserScriptInjectionTime.atDocumentStart); expect(overrideConsoleScript.source, ''' -function removeCyclicObject() { - const levelObjects = []; - return function (k, v) { - if (typeof v !== "object" || v === null) { return v; } - const currentParentObj = this; - while ( - levelObjects.length > 0 && - levelObjects[levelObjects.length - 1] !== currentParentObj - ) { - levelObjects.pop(); - } - if (levelObjects.includes(v)) { return; } - levelObjects.push(v); - return v; - }; -} - -function log(type, args) { - var message = Object.values(args) - .map(v => typeof(v) === "undefined" ? "undefined" : typeof(v) === "object" ? JSON.stringify(v, removeCyclicObject()) : v.toString()) - .map(v => v.substring(0, 3000)) // Limit msg to 3000 chars - .join(", "); - - var log = { - level: type, - message: message - }; - - window.webkit.messageHandlers.fltConsoleMessage.postMessage(JSON.stringify(log)); -} +var _flutter_webview_plugin_overrides = _flutter_webview_plugin_overrides || { + removeCyclicObject: function() { + const levelObjects = []; + return function (k, v) { + if (typeof v !== "object" || v === null) { return v; } + const currentParentObj = this; + while ( + levelObjects.length > 0 && + levelObjects[levelObjects.length - 1] !== currentParentObj + ) { + levelObjects.pop(); + } + if (levelObjects.includes(v)) { return; } + levelObjects.push(v); + return v; + }; + }, + log: function (type, args) { + var message = Object.values(args) + .map(v => typeof(v) === "undefined" ? "undefined" : typeof(v) === "object" ? JSON.stringify(v, _flutter_webview_plugin_overrides.removeCyclicObject()) : v.toString()) + .map(v => v.substring(0, 3000)) // Limit msg to 3000 chars + .join(", "); + + var log = { + level: type, + message: message + }; + + window.webkit.messageHandlers.fltConsoleMessage.postMessage(JSON.stringify(log)); + } +}; let originalLog = console.log; let originalInfo = console.info; @@ -1415,11 +1416,11 @@ let originalWarn = console.warn; let originalError = console.error; let originalDebug = console.debug; -console.log = function() { log("log", arguments); originalLog.apply(null, arguments) }; -console.info = function() { log("info", arguments); originalInfo.apply(null, arguments) }; -console.warn = function() { log("warning", arguments); originalWarn.apply(null, arguments) }; -console.error = function() { log("error", arguments); originalError.apply(null, arguments) }; -console.debug = function() { log("debug", arguments); originalDebug.apply(null, arguments) }; +console.log = function() { _flutter_webview_plugin_overrides.log("log", arguments); originalLog.apply(null, arguments) }; +console.info = function() { _flutter_webview_plugin_overrides.log("info", arguments); originalInfo.apply(null, arguments) }; +console.warn = function() { _flutter_webview_plugin_overrides.log("warning", arguments); originalWarn.apply(null, arguments) }; +console.error = function() { _flutter_webview_plugin_overrides.log("error", arguments); originalError.apply(null, arguments) }; +console.debug = function() { _flutter_webview_plugin_overrides.log("debug", arguments); originalDebug.apply(null, arguments) }; window.addEventListener("error", function(e) { log("error", e.message + " at " + e.filename + ":" + e.lineno + ":" + e.colno); From 979d8eef3a6378e67a4b918a165abcc07f030e03 Mon Sep 17 00:00:00 2001 From: LinXunFeng Date: Tue, 30 Apr 2024 09:23:40 +0800 Subject: [PATCH 08/11] Update comment --- .../lib/src/webkit_webview_controller.dart | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart index bbf38c1c3e3..88d6835eaa3 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart @@ -630,12 +630,19 @@ class WebKitWebViewController extends PlatformWebViewController { } Future _injectConsoleOverride() { - // Using the replacer parameter of JSON.stringify() to solve the error + // Within overrideScript, a series of console output methods such as + // console.log will be rewritten to pass the output content to the dart end. + // + // These output contents will first be serialized through JSON.stringify(), + // but if the output content contains cyclic objects, it will encounter the + // following error. // TypeError: JSON.stringify cannot serialize cyclic structures. // See https://github.com/flutter/flutter/issues/144535. // // Considering this is just looking at the logs printed via console.log, // the cyclic object is not important, so remove it. + // Therefore, the replacer parameter of JSON.stringify() is used and the + // removeCyclicObject method is passed in to solve the error. const WKUserScript overrideScript = WKUserScript( ''' var _flutter_webview_plugin_overrides = _flutter_webview_plugin_overrides || { From fd9bbcf3a61f3369df626da7e1d44c9d5b3ee011 Mon Sep 17 00:00:00 2001 From: LinXunFeng Date: Tue, 30 Apr 2024 12:39:39 +0800 Subject: [PATCH 09/11] Update comment --- .../lib/src/webkit_webview_controller.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart index 88d6835eaa3..f31134daa29 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart @@ -631,7 +631,8 @@ class WebKitWebViewController extends PlatformWebViewController { Future _injectConsoleOverride() { // Within overrideScript, a series of console output methods such as - // console.log will be rewritten to pass the output content to the dart end. + // console.log will be rewritten to pass the output content to the Flutter + // end. // // These output contents will first be serialized through JSON.stringify(), // but if the output content contains cyclic objects, it will encounter the From c32dedd2df8a857f71f873cdb051ecd72a623a39 Mon Sep 17 00:00:00 2001 From: LinXunFeng Date: Tue, 30 Apr 2024 13:35:25 +0800 Subject: [PATCH 10/11] Update AUTHORS --- AUTHORS | 3 ++- packages/webview_flutter/webview_flutter_wkwebview/AUTHORS | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 543b9813fe2..2d6cec4ff91 100644 --- a/AUTHORS +++ b/AUTHORS @@ -74,4 +74,5 @@ Twin Sun, LLC Amir Panahandeh Daniele Cambi Michele Benedetti -Taskulu LDA \ No newline at end of file +Taskulu LDA +LinXunFeng diff --git a/packages/webview_flutter/webview_flutter_wkwebview/AUTHORS b/packages/webview_flutter/webview_flutter_wkwebview/AUTHORS index a0cf8d9f1ca..8625e8aaa7d 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/AUTHORS +++ b/packages/webview_flutter/webview_flutter_wkwebview/AUTHORS @@ -68,3 +68,4 @@ Maurits van Beusekom Antonino Di Natale Nick Bradshaw The Vinh Luong +LinXunFeng From 37006000ef7e331628a535a62273cf8c34507729 Mon Sep 17 00:00:00 2001 From: LinXunFeng Date: Wed, 8 May 2024 08:52:30 +0800 Subject: [PATCH 11/11] Rename --- .../lib/src/webkit_webview_controller.dart | 12 ++++++------ .../test/webkit_webview_controller_test.dart | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart index f31134daa29..c152f326259 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart @@ -648,18 +648,18 @@ class WebKitWebViewController extends PlatformWebViewController { ''' var _flutter_webview_plugin_overrides = _flutter_webview_plugin_overrides || { removeCyclicObject: function() { - const levelObjects = []; + const traversalStack = []; return function (k, v) { if (typeof v !== "object" || v === null) { return v; } const currentParentObj = this; while ( - levelObjects.length > 0 && - levelObjects[levelObjects.length - 1] !== currentParentObj + traversalStack.length > 0 && + traversalStack[traversalStack.length - 1] !== currentParentObj ) { - levelObjects.pop(); + traversalStack.pop(); } - if (levelObjects.includes(v)) { return; } - levelObjects.push(v); + if (traversalStack.includes(v)) { return; } + traversalStack.push(v); return v; }; }, diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart index c63b034f585..b5f731f9735 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart @@ -1380,18 +1380,18 @@ void main() { expect(overrideConsoleScript.source, ''' var _flutter_webview_plugin_overrides = _flutter_webview_plugin_overrides || { removeCyclicObject: function() { - const levelObjects = []; + const traversalStack = []; return function (k, v) { if (typeof v !== "object" || v === null) { return v; } const currentParentObj = this; while ( - levelObjects.length > 0 && - levelObjects[levelObjects.length - 1] !== currentParentObj + traversalStack.length > 0 && + traversalStack[traversalStack.length - 1] !== currentParentObj ) { - levelObjects.pop(); + traversalStack.pop(); } - if (levelObjects.includes(v)) { return; } - levelObjects.push(v); + if (traversalStack.includes(v)) { return; } + traversalStack.push(v); return v; }; },