
Math.Round opens the browser print dialog - gokhan
https://github.com/dotnet/try/issues/290
======
ChrisSD

        var ASM_CONSTS = [(function(){
            var err = new Error;
            print('Stacktrace: \n');
            print(err.stack)
        } // ...
    

The issue is that print call. They expect it to call their own print function.
But that's not in scope so it falls back on window.print (I.e. the function
defined in the global object).

~~~
ncr100
Code coverage auditing, Test error handling.

~~~
Sharlin
Use of a language with sane scoping rules…

~~~
acdha
I’d categorize this not as scoping but the polluted global namespace in the
browser environment and JavaScript’s behavior of ignoring extra arguments.

~~~
Sharlin
It’s not a global `print` function that’s called but `window.print`, right?
`print` is sugar for `this.print` and `this` is the window object if it’s not
explicitly bound to something else. So I’d definitely say it’s a very JS-
specific scoping issue.

~~~
acdha
> It’s not a global `print` function that’s called but `window.print`, right?
> `print` is sugar for `this.print` and `this` is the window object if it’s
> not explicitly bound to something else.

This is a common point of confusion because in a browser the global object is
traditionally the same as window (or “self” or “frames”) so there wasn't a
difference for many years until ES5 introduced strict mode, which left the
default as undefined instead of silently using the global object, and things
further fractured with Node (where it's “global”) and Web Workers (where only
“self” works). (In browsers this is also complicated by the Window/WindowProxy
distinction — see [https://blog.whatwg.org/windowproxy-window-and-
location](https://blog.whatwg.org/windowproxy-window-and-location) and
especially
[https://mathiasbynens.be/notes/globalthis#terminology](https://mathiasbynens.be/notes/globalthis#terminology))

A couple years back, “globalThis” was added to make it easier to write
portable code across different environments without having to check various
names: [https://github.com/tc39/proposal-
global](https://github.com/tc39/proposal-global)

I don't think is not a particularly JavaScript-specific issue because any
language which inherits scope can have the problem of a symbol not matching
what you expected, which is why the ones which don't have compile-time
checking tend to use linters which will report use of things which haven't
been explicitly declared (not mention shadowing built-in names). If you want
to blame JavaScript, the feature which would have made this more obvious would
have been not ignoring extra arguments – print("foo") triggering an error at
that point in the source would make it more obvious.

~~~
Sharlin
Wow, that’s pretty horrible.

------
picozeta
> "But exactly which _concrete_ bugs would a programming language and
> environment with a strong type system prevent?" asked the young student
> Master Typikos.

" _These_ kind of errors." Master Typikos said - and she told the student the
story about the time when a bug in a runtime caused Math.Round to do IO
although it's type was `Integer -> Float32 -> Float32`.

The student did not believe this story. Later he was enlightened.

EDIT: refined type

~~~
mpeg
How would strong typing really prevent this? This is a side effect caused by a
scoping issue, calling window.print instead of the local print function.

~~~
H8crilA
He means Haskell-grade types (float->float is not a function touching the IO
monad). It wouldn't help in any mainstream language with actual types (like
C++).

~~~
mpeg
Right, that makes sense, I always thought that had more to do with the pure
functional nature of Haskell than the type system, but I've never written any
Haskell.

~~~
picozeta
From a certain point of view that is the same thing. A _pure_ function can
only enforced using a powerful type system. Otherwise one could argue, your
types are "lying".

EDIT: 's/strong/powerful'

------
exogen
So it's caused by a reference to `print` not being what they expected.

The create-react-app project maintains a great list of "confusing browser
globals" for exactly this situation! [https://github.com/facebook/create-
react-app/tree/master/pac...](https://github.com/facebook/create-react-
app/tree/master/packages/confusing-browser-globals)

You can use it along with ESLint to detect situations where a variable
reference is technically valid (it will refer to the window property) but is
probably not what you're intending.

Some of them are really easy to trip over, like `error`, `name`, and `open`.
All global properties on the window!

~~~
habosa
Name got me the other day. I was writing typescript and not even targeting the
browser but I guess I had browser globals in the .d.ts

I had a string like "Hello ${name}" and it would compile but crash at runtime.

Wasted a whole day, learned a lot about why even with great tools the JS
ecosystem still has some fundamental crap at the bottom.

------
a1371
So basically a library tries to print something in the console and instead of
using `console.log(...)` they use `print (...)` as if it is Python. That
instead invokes `window.print` used to actually send something to the printer.

~~~
camjohnson26
This happens because of scope chaining in JavaScript. If you call a function
it will look for it in the current context. If it’s not there it will try to
find it in the parent. If it’s not there it will keep checking the parent
objects until it finds it, or throw an exception. Since window is the top
level context and includes a print function, it gets called and shows the
printer dialog.

~~~
minitech
Not the parent objects – the containing scopes. (Which is how scope works in
most languages.)

------
keanebean86
I wish the world could decide on a standard console method. I, far too often,
catch myself typing console. in Java. It's even worse if I've done some C#
recently.

------
Groxx
I agree with
[https://github.com/dotnet/try/issues/290#issuecomment-503768...](https://github.com/dotnet/try/issues/290#issuecomment-503768091)
\- this seems pretty likely to be "you are using `print(...)` but don't have a
custom one in scope, so it's calling the window's func"

It happens in Firefox too, fwiw. Probably just a mono.js flaw.

------
yellowapple
In the process of trying to reproduce this bug in some rather silly
environments, I've instead discovered that try.dot.net is completely broken on
multiple browsers:

\- On Firefox for Android, it's impossible to type in a program, since when
typing something as simple as "using System;" it'll garble the text like crazy

\- On Android browsers in general, the Monaco editor on that page is too
"smart" for its own good and presents a worthless context menu when I press
and hold (i.e. to select all text or paste it in). Microsoft: could y'all
_not_?

\- On both the (presumably-Chromium-based) default browser on my Android phone
and Firefox 52.9.0 ESR on a reasonably "recent" OpenIndiana, the Blazor
runtime fails to run anything at all when I click "Run", complaining in the JS
console (at least on OpenIndiana; didn't check on my phone, but the symptoms
are the same) that "No .NET call dispatcher has been set".

\- On a reasonably-recent nightly version of Haiku, loading try.dot.net at all
causes WebPositive to outright crash within seconds.

~~~
zaroth
But why exactly are so many people determined to try to reproduce this
particular bug in every permutation of device/os/browser known to man?

~~~
acdha
They’re joining a “LOL JavaScript” but refusing to use the easy tools
available to understand what’s actually happening, so there’s lots of shooting
in the dark – not unlike the thread here about strong type systems.

------
mustak_im
Why does `print(...)` in Firefox acts like `console.log`?

~~~
nanny
It only acts like console.log in the browser console, not in a script.
Interesting.

~~~
panopticon
The Chrome console defines a few console-only convenience functions too:
[https://github.com/GoogleChrome/devtools-
docs/blob/master/do...](https://github.com/GoogleChrome/devtools-
docs/blob/master/docs/commandline-api.md)

------
owl57
Curious if there are any browsers and circumstances where instead of the
dialog window.print() would immediately print something.

------
patrick5415
And here I thought the story was about the endless stream of “me too” comments
in the bug report. Hard to find much signal in there.

------
shereadsthenews

      C:\>copy WEB LPT1

------
tedunangst
What is the expected behavior from calling print()?

~~~
masswerk
The JavaScript function "window.print()" is expected to open a print dialog
for the current document. Since "window" is also the global object for the
main/UI thread in a browser, "print()" resolves to "window.print()", if no
function has been defined otherwise. This is, BTW, also a potential issue in
Emscripten, which uses a similar logging mechanism by a custom "print()"
function. (I guess, this is also, where it came from in the WASM
implementation. A few years ago, I actually replaced all references to "print"
by a more safe name for a customized Emscripten runtime, in order to prevent
similar from happening in any edge cases. I suggest to treat "print" and
similar global function names just as if they were reserved words in your
projects to avoid "expectable unexpecteds" like this. For similar reasons,
using a variable "self" to store a reference to the current this-object isn't
a great idea, since "self" is already the canonical reference to the global
object…)

Edit: To be more specific, "window" is only the global object for the
scripting context in a browser window (anything inside "script" tags).
Meaning, you would have to use the full form, "window.print()", when calling
the print function from outside this context, like inside an event handler
attribute of an HTML tag. (E.g., '<button onclick="window.print()">Print
page<button>'. Here, a simple "print()" wouldn't work.)

