61

It's been a long time since we worked on Stack Snippets. I'm sorry. It's mostly because I created it, then I got promoted to management, and now I don't code much anymore and nobody else has time to work on it. So you can blame me.

But before you do blame me, read on for good news!

Thanks in large part to the efforts of canon and his MIT licensed virtual console library for Stack Snippets, we now have a virtual console!

Normally I'd do screenshots, but with Stack Snippets I can just give you a live demo instead. Check it out!

console.log("virtual!");
console.log("console!");
<b>Here's some HTML</b>

The system now offers a new "include console" checkbox in the editor window, which is selected by default. If you hate this new virtual console, you can either unselect it there, or set console: false in the Stack Snippet markdown. So everybody wins!

Special thanks again to canon who did most of the work on this upgrade!

  • 14
    Thanks for implementing this! It's very much appreciated. – canon May 18 '16 at 20:01
  • 1
    Awesome, good job! – Konamiman May 18 '16 at 20:03
  • 10
    Thank you @canon!! – T.J. Crowder May 19 '16 at 7:24
  • 3
    YES YES YES! This is the best thing since stack snippets :D – Cerbrus May 19 '16 at 8:06
  • 1
    Note to self: don't implement a console or you might get promoted again – Denys Séguret May 19 '16 at 8:18
  • Not working in Firefox ("Mozilla/5.0 (X11; Linux x86_64; rv:48.0) Gecko/20100101 Firefox/48.0") but works in Chrome ("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2723.2 Safari/537.36"). Haven't had time to debug but just quick report. – user3459110 May 19 '16 at 9:05
  • Doesn't work with stackoverflow.com/a/21457293/259953 :( Thus, it's useless – Der Hochstapler May 19 '16 at 11:18
  • 2
    Answering questions yesterday, it was so nice not having to include my workaround for this!! – T.J. Crowder May 20 '16 at 7:05
  • @AwalGarg I don't have a linux desktop environment handy. I'll look into this over the weekend. – canon May 20 '16 at 19:18
  • This needs to be featured! – Oriol May 21 '16 at 0:17
  • 1
    Good work, though here is one problem/issue that I think needs to be addressed ASAP – LGSon May 22 '16 at 19:07
  • Work on this stuff seems to have stalled again. This comment from more than two weeks ago says a minor change will be "in the next build" but it still isn't there; this significant enhancement that canon's made to the script doesn't seem to be getting any UI attention. Could we please get those in? canon's done the hard work. – T.J. Crowder Jun 6 '16 at 13:05
  • @T.J.Crowder yes it has stalled for the moment. We're still working on it but other things internally have taken priority for a few weeks. – Haney Jun 6 '16 at 14:34
  • I have create stack-snippets-console to be able to discuss, report, and propose about the console in a proper way. – Oriol Jun 12 '16 at 22:54

12 Answers 12

17

The console script has been moved to the head and now it waits until DOMContentLoaded, so console elements are inserted at the end of the body.


The console element should be inserted at the end of the body, just like the script one.

For example, the following code should log Hello! instead of <div class="as-console"></div>.

console.log(document.querySelector('div').innerHTML);
<div>Hello!</div>

It seems the problem is in content/Js/snippet-javascript.en.js

'writeResult': function () {
  var t = this,
  n = t._state.css,
  i = t._state.js,
  a = t._state.html,
  r = t._state.console;
  if ('' != n || '' != i || '' != a) {
    var o = '';
    null != p && (o = '//' + p),
    r === !0 && (a = '<script src="' + o + '/scripts/snippet-javascript-console.min.js"></script>' + a);

The last assignment should be

a += '<script src="' + o + '/scripts/snippet-javascript-console.min.js"></script>'
  • Nice catch! ... – T.J. Crowder May 22 '16 at 8:17
  • Now that I think about it, querySelector is just the tip of the iceberg. Even if moved to the end, console elements will be affected by CSS and alter the length of querySelectorAll and getElementsByTagName collections. The proper way would be moving the user input inside an iframe, and place the console in the outer page. – Oriol May 22 '16 at 18:31
  • This is already creating problems – Oriol May 22 '16 at 18:58
  • @T.J.Crowder Read up on this and help getting this fixed ASAP – LGSon May 22 '16 at 19:04
  • 1
    I ran into it in a snippet just yesterday, as I was going to do an example with a series of divs and opened it with document.querySelectorAll("div"). Moving it to the end may help some, but then it'll get mixed with any dynamically-added content, and wouldn't have helped in my case yesterday. Having the console div in the same document at all is likely to be an ongoing issue. Think it needs to be moved to a frame. – T.J. Crowder May 23 '16 at 6:33
  • 1
    @T.J.Crowder that was actually part of my original proposal down under "A real solution" (demo). I haven't looked into making nested sandboxed frames communicate with one another; so, I haven't pushed that idea yet. But yes, we should do what we can to keep the console and demo DOM separate. – canon May 23 '16 at 16:14
  • @canon Assuming the iframes have same domain, it would be something like contentIframe.contentWindow.console.log = function(){ ... } – Oriol May 23 '16 at 16:20
  • @Oriol yes, I know. But you have to know when the iframe's contentWindow becomes available... before the rest of the document is parsed. And I haven't looked into accessing the parent from the child when the frames are sandboxed. I will, though. – canon May 23 '16 at 16:21
  • @canon I was thinking something like this. But inserting snippet contents at DOMContentLoaded would break snippets which use DOMContentLoaded. – Oriol May 23 '16 at 16:55
  • @Oriol look at how the demo is implemented. Don't pay much attention to the console itself... it's a very old fork. – canon May 23 '16 at 17:01
  • @T.J.Crowder Doesn't look like the nested frames are happening anytime soon (source). – canon May 23 '16 at 20:28
  • @canon: Thanks for the head's up. FYI: meta.stackexchange.com/questions/279420/… – T.J. Crowder May 24 '16 at 13:39
13

You cannot XSS using this method, however, the console breaks on HTML style formatting inside a log statement:

console.log("<script>alert('omg');</script>");

  • 1
    I'll look into this. – canon May 18 '16 at 21:05
  • 2
    @canon must be escaping thingy. <script></script> throws, but not <a></a>. <script></script\> doesn't throw. – Meta Andrew T. May 18 '16 at 21:08
  • Keep in mind there's no huge risk here as-is. We'll get it fixed, but Stack Snippets are sandboxed and secured on a 3rd party domain. Nothing bad will come of anyone's best efforts here. :) – Haney May 18 '16 at 21:14
  • 3
    That fails even without the virtual console because the </script> borks the DOM parser. I can't do much about that. Just try putting <script>console.log("<script>alert('omg');</script>");</script> in a fresh HTML page. You'll get a console error and garbage rendered: fiddle. – canon May 18 '16 at 22:42
  • 1
    So, either we're going to have to detect </script> within string literals and escape that forward slash with some pre-processing before we set the iframe content... or we'll have to rely on people to know that HTML parsing is going to screw them. Like I said, though... this isn't an issue particular to the virtual console. – canon May 18 '16 at 23:07
  • 6
    Instead of putting the code inside of a script tag, you could use src= with a data URL (without base64, if you get the encoding right) to avoid this issue. (cc @canon) – Jeremy Banks May 18 '16 at 23:09
  • I rather like that... – canon May 18 '16 at 23:16
  • Further, if we go the data URI route, we can get meaningful line numbers as per Sci's request... at least in FireFox and Edge. Oddly, I don't get a line number in the error event handler on Chrome when the script comes from a data URI. – canon May 19 '16 at 4:43
  • 2
    Perhaps this is growing into a new feature request @canon <_< – Quill May 19 '16 at 4:44
11

The console now grows and shrinks with the available width. The box doesn't overflow any more.


The Stack Snippets console overflows on mobile devices if the viewport isn't wide enough.

This is actually just a small layout bug with a wonderful feature. (Thanks Haney!)

The post in the screenshot is this one.

  • Thanks for pointing that out. I use the mobile app and it doesn't support snippets run feature. Totally forgot about the mobile website. – canon May 19 '16 at 4:50
  • 1
    Looks like this can be fixed by applying height:100%;width:100% to the <iframe>. – canon May 20 '16 at 2:16
  • 4
    Fixed and live momentarily. – Haney May 20 '16 at 19:13
  • 1
    It is. Thanks @haney – Patrick Hofman May 20 '16 at 19:13
  • @Pat did you do that when viewing the full site theme, or mobile site theme? – Shadow The Dragon Wizard Apr 3 '17 at 9:53
  • @ShadowWizard mobile view – Patrick Hofman Apr 3 '17 at 9:54
  • Oh. And now it still works for you? – Shadow The Dragon Wizard Apr 3 '17 at 9:55
  • I can't run the snippet any more @Sha – Patrick Hofman Apr 3 '17 at 9:57
  • @Haney the snippets are not working anymore for mobile, is this on purpose? – Shadow The Dragon Wizard Apr 3 '17 at 9:57
8

(this is now implemented and live)


The virtual console currently implements log, info, warn, error, and clear, but many other console methods don't write to the virtual console (just the real one):

console.log("This uses the virtual console");
console.dir({o:"testing"}); // This doesn't
console.time("timed");      // This doesn't
console.timeEnd("timed");   // This doesn't

Aggregating data from several DSE queries (because of timeouts; links below), here are the number of questions and answers (combined) in which various console methods occur (roughly), looking only at the and tags:

console.log    287,489
console.error    4,291
console.dir      2,025
console.info     1,940
console.warn       979
console.time       431
console.timeEnd    407
console.clear      277
console.assert     155
console.dirxml      20
console.count       17

Based on that and level of difficulty, I suggest implementing:

  • dir as an alias for log initially, more can be done if appropriate but the distinction is more for interactive consoles.
  • time and timeEnd, as they're quite easy

It's clearly not feasible to expect that the virtual console will have a union of all of the features offered by Chrome, Firefox, IE, and others! But if it's going to be called console, I think to minimize surprise we need to ensure it implements the more commonly-used methods.

DSE query links:

  • Apart from dirxml() and count(), those are all implemented by my script (as of last night). Though I've probably got to add a shim for performance.now() which I use for time() and timeEnd(). – canon May 20 '16 at 17:42
  • @canon: Fantastic! Extremely good of you to take the time to enhance SE in this way. Any idea when they'll put that on the site? – T.J. Crowder May 20 '16 at 17:51
  • 1
    Going live in a few! – Haney May 20 '16 at 18:24
  • 1
    Is anyone else bothered by the disparity in time() and timeEnd() counts in T.J.'s data? – canon May 20 '16 at 19:57
  • I've added count() and dirxml() as well. – canon May 21 '16 at 3:59
  • 1
    @canon: I was! :-) – T.J. Crowder May 21 '16 at 6:56
7

Is the date in the log really necessary ?

It doubles the height of a console line and we rarely wait more than 24 hours to see how our snippet behaves (when we do, we lose the fastest gun race and nobody sees our answer so the snippet doesn't really matter).

console.log("virtual!");
console.log("console!");
<b>Here's some HTML</b>

  • 3
    Yeah, good point. I think I'll dump the date part this morning. – Haney May 19 '16 at 13:55
  • 3
    Going live in a few here. – Haney May 19 '16 at 16:36
  • @Haney much cleaner! – Denys Séguret May 19 '16 at 19:18
  • @Haney: Nice one! – T.J. Crowder May 20 '16 at 7:00
  • TBH the time isn't probably useful either... – Denys Séguret May 20 '16 at 10:04
  • 3
    Could be, for demonstrating how long something takes. – T.J. Crowder May 20 '16 at 12:11
7

Move the console outside the document.

Placing the console inside the document can produce lots of interferences. For example:

  • CSS selectors like div will select console elements
  • JS collections like document.querySelectorAll('div') will include console elements

I think the proper way would be:

  • Move the HTML, CSS and JS entered by the user inside an inner content iframe which occupies all the snippet iframe.
  • Place the console in the snippet iframe, outside the content iframe

This is how the console behaves in a browser. The content of a page can't interfere with the console.

Here's a simple example of how the console being in the same document is a problem:

console.log("This is...");
setTimeout(function() {
  var d = document.createElement('div');
  d.appendChild(document.createTextNode("...a problem"));
  document.body.appendChild(d);
}, 0);
div {
  position: relative !important;
}
<div>Hmmm</div>

Here's another example:

// Demonstration that `length` on the jQuery instance will be 0
// if there are no matching elements. There are no `div` elements
// in this snippet.
$(function() {
  console.log($("div").length);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

That demonstration should be logging 0, not 2. Moving the console out of the document entirely is the only way to prevent this kind of cross-talk between the console and the various different snippets people use to demonstrate things.

  • Thanks for reporting this bug. I have modified Stack Snippets to include the console in the <head> tag which alleviates DOM assumptions. This fix is now live. – Haney May 23 '16 at 16:06
  • 1
    @Haney Thanks, but that can't work directly. The console script appends some elements to document.body, so that will throw an error in the head. Better move the script to the end of the body, or use an event listener in the head. – Oriol May 23 '16 at 16:13
  • It has been modified to use an event listener, not to worry! – Haney May 23 '16 at 16:14
  • 1
    @Haney OK, it was a caching problem XD – Oriol May 23 '16 at 16:16
  • 2
    @Haney: While moving the script is a start, the bigger problem is that the console adds elements to body, which interact with the snippet. Have to strongly disagree with the statement that the cost/benefit isn't there. Not only worth doing, but as Oriol points out, it needs doing soon. Here's an example of how it could work: output.jsbin.com/wicofa (Source: main page, console page, example snippet) – T.J. Crowder May 24 '16 at 13:39
  • 2
    @Haney: Sorry, the first JSBin link above is to the wrong page. Here's the example: output.jsbin.com/himarux – T.J. Crowder May 25 '16 at 6:36
  • 2
    @T.J.Crowder I'm going to be writing a nested-frame version of the console. Much of the serialization will still be handled in the inner-most frame so that we don't have to worry about cloning failures when posting messages. The display will all be handled by the console frame, though. I'll be on the tavern if you'd like to chat. – canon May 25 '16 at 18:35
  • 4
    @canon: Great! Can't imagine you need any help, but the offer's there if you like. I know I've said it before, but I'll just say it one last time: I really appreciate your work on this, and I know I'm not the only one who does. It's rubbish that the only reason this is moving forward is that you're doing the work, but it's really great you're doing the work and we're fortunate to have you doing it. – T.J. Crowder May 25 '16 at 23:57
6

"Show console" (the label on the checkbox for enabling the feature as of the current UI; previously "include console") doesn't say much of anything. I suggest "Use in-snippet console" or similar, with one of those little (i) icons next to it with a fuller sentence.

  • 2
    This makes a lot of sense, gonna spend a few working something more informative up. Thanks! – Haney May 20 '16 at 15:29
  • Done and live in next build. – Haney May 20 '16 at 18:17
  • @Haney: When does that build go live? And will it include a UI for the new options? – T.J. Crowder May 28 '16 at 9:45
  • This idea was recently raised as a standalone question. – LWC Mar 15 '17 at 18:58
5

THIS IS NOW IMPLEMENTED IN THE SCRIPT (demo). Just waiting for SE to add a UI for it.


Could we add a flag saying that the console is the entire output? This would do two things:

  1. Let the console fill the result area

  2. Default to not scrolling to the end on ouput (leaving the scrolling up to the user)

In the tag, I post a lot of answers where the console output is the only output of the snippet. In those snippets, all of the Result area other than the virtual console is just wasted space. So how 'bout a "console is result" or similar checkbox:

"console is result" option

The default would be off, of course.

Here's an example from this answer — here's the snippet currently in that answer, using my rubbish workaround snippets.js script:

var str = "j and j and j x";
snippet.log("Search string: '" + str + "'");
for (var n = 0; n < str.length; ++n) {
  test(str, n);
}
function test(s, start) {
  var index = s.indexOf("j", start);
  snippet.log("Starting at " + start + ": " + index);
}
<!-- Script provides the `snippet` object, see https://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

And here it is with the lovely virtual console canon wrote for us:

var str = "j and j and j x";
console.log("Search string: '" + str + "'");
for (var n = 0; n < str.length; ++n) {
  test(str, n);
}
function test(s, start) {
  var index = s.indexOf("j", start);
  console.log("Starting at " + start + ": " + index);
}

As you can see, it shows the end of the output rather than the beginning, a lot more scrolling is required, and clicking the "Full page" link doesn't help.

  • i second that, but i would request a variable splitter, too, because the console output is fixed in size and it would be better if the size can be adjusted. – Nina Scholz May 20 '16 at 19:02
  • @NinaScholz: Thanks. I'd post the variable thing as a separate suggestion. This one is just a simple all-or-nothing. – T.J. Crowder May 21 '16 at 6:58
  • I'd love to hear from the downvoters why they don't think this would be useful. I'd be using it every day, several times a day. – T.J. Crowder May 21 '16 at 6:59
  • Personally, I don't like the idea of disabling the auto-scroll. The native console doesn't behave like that. That said, autoScroll, maxEntries, maximize, and timeStamps are among the config options I've added... though, it's up to the dev team to take advantage of them and provide UI options for you. Here's a demo. Please don't put that magic-method config() call in your source, though. Wait until the SO devs implement something to inject the call for you. – canon May 21 '16 at 13:49
  • 2
    @canon: You rock. Yes, normal consoles scroll (well, most do) and we want what you originally did as the default, no question. But the use case for most of my answers is more document.write-like, e.g., just output that usually should be read from the top down. (I just refuse to use document.write and lead people into bad habits. :-) ). So your autoScroll: false and maximize options work perfectly for that. Hope to see a way from SE to use it soon! – T.J. Crowder May 21 '16 at 15:01
  • 1
    @canon: BTW, happy to pitch in if you ever want another pair of hands in there. Just say the word. You clearly don't need the help on a technical level, but everyone has time limitations. – T.J. Crowder May 21 '16 at 15:04
  • Thanks, @T.J.Crowder ;) – canon May 21 '16 at 16:10
3

When throwing errors, it would be helpful to actually print the line that the error occurred on, especially as the line mentioned doesn't match up with the source code. Of course, it's good that it shows anything for errors.

console.log('console!!')
console.log([1,2,3])
console.log({i: 'think', this: 'is', cool: '!'})
console.log(console.log)
throw new Error('test')

  • Are you suggesting that for javascript-only snippets we offset the error line-number by all the preceding boiler-plate HTML? Because it already is based on the source... in a sense... if you view the frame source. – canon May 18 '16 at 20:17
  • Not only JS-only, but for any error that comes from the JS code, if that's possible. – Scimonster May 18 '16 at 20:24
  • Let me chew on that for a bit. Keep in mind that the native console thinks it's line #16 as well, though. – canon May 18 '16 at 20:31
  • Correct, but here at least we have some measure of control over what it shows. ;) – Scimonster May 18 '16 at 20:32
  • Or instead of adjusting the line number, just give the line of code the error occurred on, as i actually wrote in the answer. – Scimonster May 18 '16 at 20:33
  • This needs more upvotes. :-) – T.J. Crowder May 20 '16 at 16:42
  • @T.J.Crowder see this suggestion and following comments. – canon May 20 '16 at 19:16
3

I can't put a bounty on this answer, so I've raised a formal feature-request instead. If you want this done, please go upvote and or bounty as appropriate.

@canon has implemented several useful options in the script (there's a demo here). Please add a UI for them so people don't start using console.config directly.

I'd suggest making it a Console Options button or some such that shows options driven by the script itself, so that when an option is added to the script, the UI for it can be added at the same time. The options would be serialized to JSON and inserted in the stack snippet's introductory comment node.

For instance, where a snippet might currently start with this:

<!-- begin snippet: js hide: false console: true -->

If the user uses the dialog to set options, it might look like this:

<!-- begin snippet: js hide: false console: true console-options: {"maximize":true,"autoScroll":false} -->

Those options get converted into a hidden call to console.config at the beginning of the snippet script.

2

Do not include the console by default, at least until it has been stabilized.

Including the console has collateral effects like Bug in stack snippet?.

People which creates snippets may not realize that this is a bug which (hopefully) will be fixed. So they might rely on the buggy behavior.

Then, once the fix lands, these snippets will break.

Not including the console by default would alleviate this possibility. Moreover, even if the console will be useful to lots of snippets, I think they are still a minority.

Only once the console has been stabilized, it might be considered to enable it by default.

  • 1
    Thanks for reporting this bug. I have modified Stack Snippets to include the console in the <head> tag which alleviates DOM assumptions. This fix is now live. – Haney May 23 '16 at 16:06
2

Logging events directly to the console causes the browser to whirrr for a couple of seconds (probably trying to stringify the whole subtree), and throw some errors (in the same console).

Also, it takes a lot longer than necessary to execute the console.log statement (due to the entire stringification process I guess.)

It currently takes roughly 2-3 seconds for me in Chrome 61. Here's how it looks in the browser console:

image

function clicked(event) {
  var startTime = new Date();
  console.log(event);
  var endTime = new Date();
  
  console.log("Total time (ms): " + (endTime - startTime));
}
<button onclick="clicked(event)">Click me</button>

  • Almost 16 seconds for me – Andrew Myers Apr 10 '18 at 13:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .