Opened 5 years ago

Closed 4 years ago

Last modified 3 years ago

#18197 closed enhancement (fixed)

Enhance dojo/kernel module to fix IE9's problematic console object - ensure console methods are functions, not objects

Reported by: jdtang Owned by: dylan
Priority: undecided Milestone: 1.7.9
Component: Core Version: 1.9.3
Keywords: Cc:
Blocked By: Blocking:

Description

Internet Explorer 9 doesn't give the console object permanent residency as part of the DOM – you have to open the developer tools for any tab you want the object to be made available to first. Besides that, when the developer tool bar is opened, if we call console.warn.apply, a JS error will occur - "Object doesn't support property or method 'apply'". This is because that the console object being injected into the window by the developer tools is not an instances of Function like all the most other DOM methods. If you call type of "console.warn", it returns "object".

Actually this design is causing problem when we write codes related with console object. For example, we want to write logs when console.warn is called, and write the following codes: aspect.after(console, "warn", lang.hitch(this, "consoleHandler");

In IE9, console object doesn't exist when developer tool bar is not opened. Fortunately, dojo/kernel will create a console object with fake methods. This is good, so that the above code will work, and we don't need to check whether console object exists. However, when developer tool bar is opened, the JS error "Object doesn't support property or method 'apply'" occurs, as the IE native console object is used, and console.warn.apply doesn't exist (aspect.after will call console.warn.apply internally).

To fix this problem, we can use the following codes to convert the native console.warn to an real function.

console.warn = Function.prototype.bind.call(console.warn, console);

After the above code is executed, we will be able to call console.warn.apply and the JS error will be fixed.

A detailed discussion of this problem and general fix can be found here: http://whattheheadsaid.com/2011/04/internet-explorer-9s-problematic-console-object

We hope that dojo could include the fix in kernel.js, reasons:

  1. It's a common problem, which would also occur when other users try to call "apply" on IE9's native console methods. You can see that multiple persons reported this problem on stackoverf

Attachments (2)

kernel.js.patch (1.1 KB) - added by jdtang 5 years ago.
proposedFix
2014-07-30_12-22-34.png (8.6 KB) - added by jdtang 5 years ago.
console_warn_is_not_function

Download all attachments as: .zip

Change History (20)

Changed 5 years ago by jdtang

Attachment: kernel.js.patch added

proposedFix

Changed 5 years ago by jdtang

Attachment: 2014-07-30_12-22-34.png added

console_warn_is_not_function

comment:1 Changed 5 years ago by jdtang

Looks like the ticket system has limitation on the length of the text in description. Adding the remaining text here.

We hope that dojo could include the fix in kernel.js, reasons:

  1. It's a common problem, which would also occur when other users try to call "apply" on IE9's native console methods. You can see that multiple persons reported this problem on stackoverflow - links can be found in the article above
  2. dojo/kernel already has codes to ensure the console object exists. We can fix this problem in the same place, by making very minor changes. After adding this fix, dojo/kernel will ensure the console object exists and console methods are real functions.

comment:2 Changed 4 years ago by dylan

Milestone: tbd1.11
Owner: set to dylan
Status: newassigned

Will do my best to address this for Dojo 1.11.

comment:3 Changed 4 years ago by dylan

@jdtang, for future contributions, please make sure you have a CLA on file ( http://dojofoundation.org/about/claForm )? In this case, it's a two-line patch, though I'm going to rewrite one line to be a feature test, so I'll accept it without a CLA, but please file one when you get a chance.

comment:5 Changed 3 years ago by Dylan Schiemann <dylan@…>

In 5d9b78b/dojo:

Error: Processor CommitTicketReference failed
Unsupported version control system "git": Can't find an appropriate component, maybe the corresponding plugin was not enabled? 

comment:6 Changed 3 years ago by Dylan Schiemann <dylan@…>

In d054eaf/dojo:

Error: Processor CommitTicketReference failed
Unsupported version control system "git": Can't find an appropriate component, maybe the corresponding plugin was not enabled? 

comment:7 Changed 3 years ago by Dylan Schiemann <dylan@…>

In 242f3b89/dojo:

Error: Processor CommitTicketReference failed
Unsupported version control system "git": Can't find an appropriate component, maybe the corresponding plugin was not enabled? 

comment:8 Changed 3 years ago by Dylan Schiemann <dylan@…>

In f804de4c/dojo:

Error: Processor CommitTicketReference failed
Unsupported version control system "git": Can't find an appropriate component, maybe the corresponding plugin was not enabled? 

comment:9 Changed 3 years ago by Dylan Schiemann <dylan@…>

In 2375cf6/dojo:

Error: Processor CommitTicketReference failed
Unsupported version control system "git": Can't find an appropriate component, maybe the corresponding plugin was not enabled? 

comment:10 Changed 3 years ago by Dylan Schiemann <dylan@…>

In 84280d2/dojo:

Error: Processor CommitTicketReference failed
Unsupported version control system "git": Can't find an appropriate component, maybe the corresponding plugin was not enabled? 

comment:11 Changed 3 years ago by sergkam

has.add("console-as-object", Function.prototype.bind && console && typeof console.log === "object");

This line in patch brakes IE11 in IE9 emulation mode. Any attempt to use or check "console" fails because "console" does not exists in this mode. you have to check "windows.console" instead of just "console" like this.

has.add("console-as-object", Function.prototype.bind && windows.console && typeof windows.console.log === "object");

typeof windows.console != "undefined" | | (windows.console = {}); intentional assignment

comment:12 Changed 3 years ago by dylan

Hi @sergkam, have you seen https://github.com/dojo/dojo/commit/5d9b78b02f3e2d934f23c54dd6a82dc8a370ebc5 . Is this really needed if it's a function return statement? And I assume you meant window.console rather than console?

The challenge with your suggestion is that there are environments that dojo supports without a window object...

comment:13 Changed 3 years ago by bill

The challenge with your suggestion is that there are environments that dojo supports without a window object...

Would testing typeof console !== "undefined" make more sense? You're right that testing window.console will break non-browser environments, but sergkam is right that the code you checked in will throw an exception when console is undefined.

comment:14 Changed 3 years ago by dylan

While true, I don't see how that code path would ever actually be reached now, because we have this code:

has.add("console-as-object", function () {
	return Function.prototype.bind && console && typeof console.log === "object";
});

typeof console !== "undefined" || (console = {});  // intentional assignment

Because has.add was switched to a function call, it's evaluation is delayed until the test is needed the first time. The subsequent line creates an empty console object if the console was undefined.

That said, https://github.com/dojo/dojo/pull/218 is a PR in case I'm missing something that this change is needed even after the switch to making the new feature test be a function.

Last edited 3 years ago by dylan (previous) (diff)

comment:15 Changed 3 years ago by bill

It's true that function call is delayed until the first call to has("console-as-object"), but what makes you think that has("console-as-object") will never be called? Probably it's not called during builds, but I would expect it to be called during regular running of dojo.

comment:16 Changed 3 years ago by dylan

@bill, I did not say it will never be called, I said that by the time it is called, the following line will have already been called:

typeof console !== "undefined" || (console = {});  // intentional assignment

And so if the console object was undefined, it will now be an empty object by the first time the console-as-object test is called.

As noted, I've made a PR to make this change, I'm asking if it's really necessary though with the change made a few days ago to change it to a function call.

comment:17 Changed 3 years ago by bill

Oh I see... yah seems like it's not necessary. I couldn't find a case where the current code fails, although IE is weird in that it acts different when developer tools is/isn't open, so maybe @sergkam can produce a test case that fails.

comment:18 Changed 3 years ago by sergkam

The bug was found after upgrading to dojo 1.11.1 (last current) When you are using IE11 in I9 compatible mode with dev console off.(Just simple dojo.js loading, no fancy configuration) As a workaround I disabled "dojo-guarantee-console" and use our own console polyfill.

I also tryed this fix (moving check to function) https://github.com/dojo/dojo/commit/5d9b78b02f3e2d934f23c54dd6a82dc8a370ebc5 and it looks like fix the problem. Thank you. I'm waiting for next release now.

Note: See TracTickets for help on using tickets.