Skip to content

Commit

Permalink
Revised attempt at browser logging
Browse files Browse the repository at this point in the history
  • Loading branch information
jgerigmeyer committed May 15, 2023
1 parent ec59edd commit d30dd42
Show file tree
Hide file tree
Showing 11 changed files with 107 additions and 33 deletions.
4 changes: 2 additions & 2 deletions lib/src/async_import_cache.dart
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,12 @@ class AsyncImportCache {
PackageConfig? packageConfig,
Logger? logger})
: _importers = _toImporters(importers, loadPaths, packageConfig),
_logger = logger ?? const Logger.stderr();
_logger = logger ?? Logger.stderr();

/// Creates an import cache without any globally-available importers.
AsyncImportCache.none({Logger? logger})
: _importers = const [],
_logger = logger ?? const Logger.stderr();
_logger = logger ?? Logger.stderr();

/// Converts the user's [importers], [loadPaths], and [packageConfig]
/// options into a single list of importers.
Expand Down
6 changes: 3 additions & 3 deletions lib/src/import_cache.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// DO NOT EDIT. This file was generated from async_import_cache.dart.
// See tool/grind/synchronize.dart for details.
//
// Checksum: 1273c347383da4775032276417fd7568c7e5330b
// Checksum: 62a3680f744d9ee34989dac0980f788ecf694070
//
// ignore_for_file: unused_import

Expand Down Expand Up @@ -90,12 +90,12 @@ class ImportCache {
PackageConfig? packageConfig,
Logger? logger})
: _importers = _toImporters(importers, loadPaths, packageConfig),
_logger = logger ?? const Logger.stderr();
_logger = logger ?? Logger.stderr();

/// Creates an import cache without any globally-available importers.
ImportCache.none({Logger? logger})
: _importers = const [],
_logger = logger ?? const Logger.stderr();
_logger = logger ?? Logger.stderr();

/// Converts the user's [importers], [loadPaths], and [packageConfig]
/// options into a single list of importers.
Expand Down
9 changes: 9 additions & 0 deletions lib/src/io/interface.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ class FileSystemException {
String? get path => throw '';
}

abstract class Console {
external void log(String data);
external void info(String data);
external void warn(String data);
external void error(String data);
}

Console? get console => throw '';

/// The standard error for the current process.
Stderr get stderr => throw '';

Expand Down
35 changes: 14 additions & 21 deletions lib/src/io/node.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import 'dart:convert';
import 'dart:js_util';

import 'package:js/js.dart';
import 'package:node_interop/console.dart';
import 'package:node_interop/fs.dart';
import 'package:node_interop/node_interop.dart' hide process;
import 'package:node_interop/node_interop.dart' as n hide process;
import 'package:node_interop/stream.dart';
import 'package:path/path.dart' as p;
import 'package:source_span/source_span.dart';
Expand All @@ -18,7 +19,9 @@ import '../exception.dart';
import '../node/chokidar.dart';

@JS('process')
external final Process? process; // process is null in the browser
external final n.Process? process; // process is null in the browser

Console? get console => n.console;

class FileSystemException {
final String message;
Expand All @@ -30,24 +33,14 @@ class FileSystemException {
}

class Stderr {
final Writable? _stderr;
final Writable _stderr;

Stderr(this._stderr);

void write(Object object) {
if (_stderr == null) {
console.error(object.toString());
} else {
_stderr?.write(object.toString());
}
}
void write(Object object) => _stderr.write(object.toString());

void writeln([Object? object]) {
if (_stderr == null) {
console.error("${object ?? ''}\n");
} else {
_stderr?.write("${object ?? ''}\n");
}
_stderr.write("${object ?? ''}\n");
}

void flush() {}
Expand Down Expand Up @@ -122,7 +115,7 @@ Future<String> readStdin() async {
}

/// Cleans up a Node system error's message.
String _cleanErrorMessage(JsSystemError error) {
String _cleanErrorMessage(n.JsSystemError error) {
// The error message is of the form "$code: $text, $syscall '$path'". We just
// want the text.
return error.message.substring("${error.code}: ".length,
Expand All @@ -143,7 +136,7 @@ bool fileExists(String path) {
try {
return fs.statSync(path).isFile();
} catch (error) {
var systemError = error as JsSystemError;
var systemError = error as n.JsSystemError;
if (systemError.code == 'ENOENT') return false;
rethrow;
}
Expand All @@ -164,7 +157,7 @@ bool dirExists(String path) {
try {
return fs.statSync(path).isDirectory();
} catch (error) {
var systemError = error as JsSystemError;
var systemError = error as n.JsSystemError;
if (systemError.code == 'ENOENT') return false;
rethrow;
}
Expand All @@ -179,7 +172,7 @@ void ensureDir(String path) {
try {
fs.mkdirSync(path);
} catch (error) {
var systemError = error as JsSystemError;
var systemError = error as n.JsSystemError;
if (systemError.code == 'EEXIST') return;
if (systemError.code != 'ENOENT') rethrow;
ensureDir(p.dirname(path));
Expand Down Expand Up @@ -229,15 +222,15 @@ T _systemErrorToFileSystemException<T>(T callback()) {
try {
return callback();
} catch (error) {
if (error is! JsSystemError) rethrow;
if (error is! n.JsSystemError) rethrow;
throw FileSystemException._(_cleanErrorMessage(error), error.path);
}
}

final Stderr stderr = () {
var stderr_ = process?.stderr;
if (stderr_ == null) {
return Stderr(null);
throw UnsupportedError("stderr is only supported on Node.js");
}
return Stderr(stderr_);
}();
Expand Down
9 changes: 9 additions & 0 deletions lib/src/io/vm.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ export 'dart:io' show exitCode, FileSystemException;

io.Stdout get stderr => io.stderr;

abstract class Console {
external void log(String data);
external void info(String data);
external void warn(String data);
external void error(String data);
}

Console? get console => throw '';

bool get isWindows => io.Platform.isWindows;

bool get isMacOS => io.Platform.isMacOS;
Expand Down
9 changes: 8 additions & 1 deletion lib/src/logger.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import 'package:source_span/source_span.dart';
import 'package:stack_trace/stack_trace.dart';

import 'deprecation.dart';
import 'io.dart';
import 'logger/deprecation_handling.dart';
import 'logger/browser.dart';
import 'logger/stderr.dart';

/// An interface for loggers that print messages produced by Sass stylesheets.
Expand All @@ -21,7 +23,12 @@ abstract class Logger {

/// Creates a logger that prints warnings to standard error, with terminal
/// colors if [color] is `true` (default `false`).
const factory Logger.stderr({bool color}) = StderrLogger;
factory Logger.stderr({bool color = false}) {
if (isBrowser) {
return BrowserLogger(color: color);
}
return StderrLogger(color: color);
}

/// Emits a warning with the given [message].
///
Expand Down
56 changes: 56 additions & 0 deletions lib/src/logger/browser.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright 2018 Google Inc. Use of this source code is governed by an
// MIT-style license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

import 'package:path/path.dart' as p;
import 'package:source_span/source_span.dart';
import 'package:stack_trace/stack_trace.dart';

import '../io.dart';
import '../logger.dart';
import '../utils.dart';

/// A logger that prints warnings to browser console.
class BrowserLogger implements Logger {
/// Whether to use colors in messages.
final bool color;

const BrowserLogger({this.color = false});

void warn(String message,
{FileSpan? span, Trace? trace, bool deprecation = false}) {
var result = '';
if (color) {
// Bold yellow.
result += '\u001b[33m\u001b[1m';
if (deprecation) result += 'Deprecation ';
result += 'Warning\u001b[0m';
} else {
if (deprecation) result += 'DEPRECATION ';
result += 'WARNING';
}

if (span == null) {
result += ': $message\n';
} else if (trace != null) {
// If there's a span and a trace, the span's location information is
// probably duplicated in the trace, so we just use it for highlighting.
result += ': $message\n\n${span.highlight(color: color)}\n';
} else {
result += ' on ${span.message("\n" + message, color: color)}\n';
}

if (trace != null) result += '${indent(trace.toString().trimRight(), 4)}\n';
console?.error(result);
}

void debug(String message, SourceSpan span) {
var result = '';
var url =
span.start.sourceUrl == null ? '-' : p.prettyUri(span.start.sourceUrl);
result += '$url:${span.start.line + 1} ';
result += color ? '\u001b[1mDebug\u001b[0m' : 'DEBUG';
result += ': $message\n';
console?.warn(result);
}
}
2 changes: 1 addition & 1 deletion lib/src/parse/parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class Parser {
Parser(String contents,
{Object? url, Logger? logger, InterpolationMap? interpolationMap})
: scanner = SpanScanner(contents, sourceUrl: url),
logger = logger ?? const Logger.stderr(),
logger = logger ?? Logger.stderr(),
_interpolationMap = interpolationMap;

String _parseIdentifier() {
Expand Down
2 changes: 1 addition & 1 deletion lib/src/visitor/async_evaluate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ class _EvaluateVisitor
? importCache ?? AsyncImportCache.none(logger: logger)
: null,
_nodeImporter = nodeImporter,
_logger = logger ?? const Logger.stderr(),
_logger = logger ?? Logger.stderr(),
_quietDeps = quietDeps,
_sourceMap = sourceMap,
// The default environment is overridden in [_execute] for full
Expand Down
4 changes: 2 additions & 2 deletions lib/src/visitor/evaluate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// DO NOT EDIT. This file was generated from async_evaluate.dart.
// See tool/grind/synchronize.dart for details.
//
// Checksum: 3e5e09dec7a8bcc6bc017103c67f463843b7fed7
// Checksum: ebae617f3ffce6fd036874e06626c391d37a962b
//
// ignore_for_file: unused_import

Expand Down Expand Up @@ -340,7 +340,7 @@ class _EvaluateVisitor
? importCache ?? ImportCache.none(logger: logger)
: null,
_nodeImporter = nodeImporter,
_logger = logger ?? const Logger.stderr(),
_logger = logger ?? Logger.stderr(),
_quietDeps = quietDeps,
_sourceMap = sourceMap,
// The default environment is overridden in [_execute] for full
Expand Down
4 changes: 2 additions & 2 deletions test/dart_api/logger_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,9 @@ class _TestLogger implements Logger {
_warn;
final void Function(String, SourceSpan) _debug;

_TestLogger.withWarn(this._warn) : _debug = const Logger.stderr().debug;
_TestLogger.withWarn(this._warn) : _debug = Logger.stderr().debug;

_TestLogger.withDebug(this._debug) : _warn = const Logger.stderr().warn;
_TestLogger.withDebug(this._debug) : _warn = Logger.stderr().warn;

void warn(String message,
{FileSpan? span, Trace? trace, bool deprecation = false}) =>
Expand Down

0 comments on commit d30dd42

Please sign in to comment.