Skip to content

Commit

Permalink
[macos] Register log handler
Browse files Browse the repository at this point in the history
Previously, the macOS embedder relied on the deprecated built-in log
handling in lib/ui/ui_dart_state.cc. Instead, we now register a
dedicated log handler for the macOS embedder. This is used, for example,
to output Dart 'print' calls.

While unlikely that we'll break the internal generic fallback logging,
it's preferable to keep platform-specific functionality in the embedder.

Issue: flutter/flutter#99636
  • Loading branch information
cbracken committed Mar 6, 2022
1 parent b2ba494 commit 6cf7c75
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 2 deletions.
8 changes: 8 additions & 0 deletions shell/platform/darwin/macos/framework/Source/FlutterEngine.mm
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h"

#include <algorithm>
#include <iostream>
#include <vector>

#import "flutter/shell/platform/darwin/macos/framework/Source/AccessibilityBridgeMacDelegate.h"
Expand Down Expand Up @@ -298,6 +299,13 @@ - (BOOL)runWithEntrypoint:(NSString*)entrypoint {
flutterArguments.dart_entrypoint_argc = dartEntrypointArgs.size();
flutterArguments.dart_entrypoint_argv = dartEntrypointArgs.data();
flutterArguments.root_isolate_create_callback = _project.rootIsolateCreateCallback;
flutterArguments.log_message_callback = [](const char* tag, const char* message,
void* user_data) {
if (tag && tag[0]) {
std::cout << tag << ": ";
}
std::cout << message << std::endl;
};

static size_t sTaskRunnerIdentifiers = 0;
const FlutterTaskRunnerDescription cocoa_task_runner_description = {
Expand Down
25 changes: 25 additions & 0 deletions shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,31 @@ @interface FlutterEngine (Test)
EXPECT_TRUE(called);
}

TEST_F(FlutterEngineTest, CanLogToStdout) {
// Replace stdout stream buffer with our own.
std::stringstream buffer;
std::streambuf* old_buffer = std::cout.rdbuf();
std::cout.rdbuf(buffer.rdbuf());

// Launch the test entrypoint.
FlutterEngine* engine = GetFlutterEngine();
EXPECT_TRUE([engine runWithEntrypoint:@"canLogToStdout"]);
EXPECT_TRUE(engine.running);

// Block until completion of print statement.
fml::AutoResetWaitableEvent latch;
AddNativeCallback("SignalNativeTest",
CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) { latch.Signal(); }));
latch.Wait();

// Restore old stdout stream buffer.
std::cout.rdbuf(old_buffer);

// Verify hello world was written to stdout.
std::string logs = buffer.str();
EXPECT_TRUE(logs.find("Hello logging") != std::string::npos);
}

TEST_F(FlutterEngineTest, CanToggleAccessibility) {
FlutterEngine* engine = GetFlutterEngine();
// Capture the update callbacks before the embedder API initializes.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,17 @@
// found in the LICENSE file.

import 'dart:ui';

void signalNativeTest() native 'SignalNativeTest';

void main() {
}

@pragma('vm:entry-point')
void canLogToStdout() {
// Emit hello world message to output then signal the test.
print('Hello logging');
signalNativeTest();
}

Picture CreateSimplePicture() {
Expand All @@ -29,8 +38,6 @@ void can_composite_platform_views() {
PlatformDispatcher.instance.scheduleFrame();
}

void signalNativeTest() native 'SignalNativeTest';

@pragma('vm:entry-point')
void native_callback() {
signalNativeTest();
Expand Down

0 comments on commit 6cf7c75

Please sign in to comment.