-
Notifications
You must be signed in to change notification settings - Fork 589
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: redirect console output #542
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice addition thanks for the PR.
I've put some suggestions of how we could improve it a little.
o := &Otto{ | ||
runtime: newContext(), | ||
} | ||
o.runtime.otto = o | ||
o.runtime.traceLimit = 10 | ||
for _, opt := range opts { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: lets set the default so we can simplify the use after.
for _, opt := range opts { | |
o.runtime.console = os.Stdout | |
for _, opt := range opts { |
var w io.Writer | ||
if call.runtime.stdoutWriter != nil { | ||
w = call.runtime.stdoutWriter | ||
} else { | ||
w = os.Stdout | ||
} | ||
fmt.Fprintln(w, formatForConsole(call.ArgumentList)) //nolint:errcheck // Nothing we can do if this fails. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: with the use of a default we can simply this.
var w io.Writer | |
if call.runtime.stdoutWriter != nil { | |
w = call.runtime.stdoutWriter | |
} else { | |
w = os.Stdout | |
} | |
fmt.Fprintln(w, formatForConsole(call.ArgumentList)) //nolint:errcheck // Nothing we can do if this fails. | |
fmt.Fprintln(call.runtime.console, formatForConsole(call.ArgumentList)) //nolint:errcheck // Nothing we can do if this fails. |
var w io.Writer | ||
if call.runtime.stdoutWriter != nil { | ||
w = call.runtime.stdoutWriter | ||
} else { | ||
w = os.Stdout | ||
} | ||
fmt.Fprintln(w, formatForConsole(call.ArgumentList)) //nolint:errcheck // Nothing we can do if this fails. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: simplify as above.
var w io.Writer | |
if call.runtime.stdoutWriter != nil { | |
w = call.runtime.stdoutWriter | |
} else { | |
w = os.Stdout | |
} | |
fmt.Fprintln(w, formatForConsole(call.ArgumentList)) //nolint:errcheck // Nothing we can do if this fails. | |
fmt.Fprintln(call.runtime.console, formatForConsole(call.ArgumentList)) //nolint:errcheck // Nothing we can do if this fails. |
@@ -775,3 +779,11 @@ func (o Object) MarshalJSON() ([]byte, error) { | |||
} | |||
return json.Marshal(goValue) | |||
} | |||
|
|||
type Option func(*Otto) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: lets document the type.
func WithStdoutWriter(w io.Writer) Option { | ||
return func(o *Otto) { | ||
o.runtime.stdoutWriter = w |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: lets document the type and change the naming so it easier for the user to understand the impact of using this option.
func WithStdoutWriter(w io.Writer) Option { | |
return func(o *Otto) { | |
o.runtime.stdoutWriter = w | |
// WithConsoleOutput sets the target for console output. | |
// Default: Stdout. | |
func WithConsoleOutput(w io.Writer) Option { | |
return func(o *Otto) { | |
o.runtime.console = w |
func TestOtterStdoutWriter(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
script string | ||
expect string | ||
}{ | ||
{ | ||
name: "console.log", | ||
script: "console.log('hello', 'world')", | ||
expect: "hello world\n", | ||
}, | ||
{ | ||
name: "console.err", | ||
script: "console.error('error', 'world')", | ||
expect: "error world\n", | ||
}, | ||
} | ||
|
||
for _, tc := range tests { | ||
t.Run(tc.name, func(t *testing.T) { | ||
var buf = &bytes.Buffer{} | ||
vm := New(WithStdoutWriter(buf)) | ||
_, err := vm.Run(tc.script) | ||
require.NoError(t, err) | ||
require.Equal(t, tc.expect, buf.String()) | ||
}) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: can we use sub tests vs table driven as its more concise and allows developers to run specific tests directly from their editor e.g. VS Code.
Also the use of just a declared buffer vs instantiated is more idiomatic.
Not tested the below, so there might be typos, but you get the idea 😃
func TestOtterStdoutWriter(t *testing.T) { | |
tests := []struct { | |
name string | |
script string | |
expect string | |
}{ | |
{ | |
name: "console.log", | |
script: "console.log('hello', 'world')", | |
expect: "hello world\n", | |
}, | |
{ | |
name: "console.err", | |
script: "console.error('error', 'world')", | |
expect: "error world\n", | |
}, | |
} | |
for _, tc := range tests { | |
t.Run(tc.name, func(t *testing.T) { | |
var buf = &bytes.Buffer{} | |
vm := New(WithStdoutWriter(buf)) | |
_, err := vm.Run(tc.script) | |
require.NoError(t, err) | |
require.Equal(t, tc.expect, buf.String()) | |
}) | |
} | |
} | |
func TestOtto_WithConsoleOutput(t *testing.T) { | |
t.Run('console.log', func(t *testing.T) { | |
var buf bytes.Buffer | |
vm := New(WithConsoleOutput(&buf)) | |
_, err := vm.Run("console.log('hello', 'world')") | |
require.NoError(t, err) | |
require.Equal(t, "hello world\n", buf.String()) | |
}) | |
t.Run('console.err', func(t *testing.T) { | |
var buf bytes.Buffer | |
vm := New(WithConsoleOutput(&buf)) | |
_, err := vm.Run("console.error('world')") | |
require.NoError(t, err) | |
require.Equal(t, "error world\n", buf.String()) | |
}) | |
} |
@@ -66,6 +67,7 @@ type runtime struct { | |||
stackLimit int | |||
traceLimit int | |||
lck sync.Mutex | |||
stdoutWriter io.Writer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: make it clear the use vs the value
stdoutWriter io.Writer | |
console io.Writer |
Add ability to re-direct
console.log()
toio.Writer
instead of os.Stdout.example