I want to use the great Promise interface described on MDN (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) with my Firefox OS app. But as of Firefox 1.3 (simulator) it doesn't seem to be supported ("Promise is undefined").
Is there a working polyfill whose syntax agrees with the specification on MDN? I don't want to rewrite everything once the real Promises interface is supported by a future version.
This one doesn't work in Firefox OS with Web Workers: https://github.com/jakearchibald/es6-promise The reason: It makes use of the "window" global variable.
This one slightly differes from the MDN specification: https://github.com/slightlyoff/Promises - Namely: While the MDN specification says
new Promise(function (resolve, reject) { /*...*/ resolve(); /*...*/ });
... this polyfill wants to use this syntax (it uses a so called "resolver"):
new Promise(function (r) { /*...*/ r.resolve(); /*...*/ });
I've just tried the simulator and can just get the promises working on a certified apps. Actually if you get the simulator, and debug any app that comes with the simulator (dialer, camera ...), you'll have a console and there you can inspect the available resources, you'll see how Promises is available.
Also tried on a phone, running gecko master, and it's available at least for privilege apps.
Just an idea that came to my mind, if you go to Tools > Add-ons you can see the simulator as an extension, in preferences it has an option to select your binary, perhaps you could download a latest build from here:
http://ftp.mozilla.org/pub/mozilla.org/b2g/nightly/latest-mozilla-central/
and give it a try.
Just putting a simple
var window = self;
in my Web Worker will make the polyfill from https://github.com/jakearchibald/es6-promise work.
It is an answer, and it at least works around the problem. Still, I'm not happy with it. It seems to me like defining a global window variable in the worker scope will have fatal consequences sooner or later - e.g. when some included JavaScript library tries to check whether it's running inside of a Web Worker etc.
However a fix is in the making: https://github.com/jakearchibald/es6-promise/pull/6
Related
We're developing a modern JS library which uses the ES6 syntax heavily and doesn't support IE11.
However we have a small number of users who want to use our library on IE11-compatible sites and we don't want to break their sites on IE11.
Question: is there some way to prevent our library from "exploding" on IE11? (All of the library functions can do nothing and return undefined if IE11 is detected)
For example, we were trying the following approach based on browser detection:
function libFunction() {
if(isIe11()) {
return;
}
// otherwise do some real stuff with ES6-heavy code
}
However the approach above doesn't work because IE11 throws syntax error even in the code that never gets executed, se we end up with errors like:
SCRIPT1002: Syntax error
File: main.db33ab01aedf59e2f70a.hot-update.js, Line: 47, Column: 1
Other approaches that we consider:
make our server return a fake implementation of our library if IE11 User-Agent is detected in the request headers. This will partially solve our problems, but won't help the users, who integrate our library into their bundle via NPM/webpack instead of getting it from our servers at runtime.
transiple our ES6 code to IE11-friendly code and polyfill all the APIs - we don't do that because we don't want the modern browser users to pay the price of the bloated ES5 code and polyfills.
override global error handler to silence the errors - this won't work, because the errors we get are syntax error, that are not handled by the error handler.
Is there any other possible solution?
While debugging application most of the time I feel like it would hve easier if I could include any library into browser console and try some of the function from that libraty.
Now in modern javascript/es6/es6/typescript world is there any thing short and quick available to to import a script instantly to the brower so that it can be used to directly
Example
While debugging, if I want Observable I should be able to do something like this
import {Observable} from 'rxjs/Observable'; //typescript way
const Observable= require('rxjs/Observable'); // require way
But these are not working.
already explored dynamic <script> tag
I already explore old way to dynamically using the <script> tag like below but its dificult for large number of libs and also not elegant
var jq = document.createElement('script');
jq.src = "https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js";
document.getElementsByTagName('head')[0].appendChild(jq);
// ... give time for script to load, then type (or see below for non wait option)
jQuery.noConflict();
Some browsers (including Chrome) can use snippets in console, either as built-in features or extensions.
One-liner script to do this is
document.head.appendChild(Object.assign(
document.createElement('script'),
{ src: '...' }
));
Considering that most websites already have jQuery loaded (even if they don't, this can be handled by browser extensions, such as Chrome jQuery Injector) it can be shortened to:
$.getScript('...');
Any piece of code that should be always available in console can also be exposed as global function with user scripts (Tampermonkey in Chrome, etc), with some limitations imposed by user script security.
This will probably will be possible with dynamic import(), which is currently stage 3 proposal and isn't implemented in browsers.
A suitable solution that works for most major libraries the one may be curious to quickly experiment with is to navigate to official library website and open the console. Due to the fact that the websites often provide live examples, relevant variables are exposed to global scope. Known examples are $ for jQuery, angular for AngularJS, ng for Angular, Rx for RxJS, moment for Moment.js...
I would like to use console.log(message) to write out some information to the browser console. However, I came across this url which seems to recommend against it:
https://developer.mozilla.org/en-US/docs/Web/API/Console/log
Are you currently choosing to use console.log(message) as part of your js code? If not then have you identified an alternative?
I agree with Mike C above-- console is generally available in most browsers, but you should probably remove console logs before a site gets pushed to production.
Additionally, some older browser might not have the console, and if you did accidentally leave in a console log, it would fire an error when it attempted to interact with with something that wasn't defined. As an extra failsafe, you can declare console and console.log in the global namespace if they are not detected, just in case:
if (!console) {
console = {
log: function () { //noop }
};
}
should I use a js function other than console.log(message)?
simple answer is yes, But also the console.log(message) is usaually used for testing purposes and for other relevant intentions like letting other developers interract with your js source code in some sort.
However.
You should not use it to log very important messages as this could be a hole your application presumably.
Hope it helps.
While the console object is not defined in the official Javascript standard, it is specified in:
Google Chrome
Mozilla Firefox
Internet Explorer 9+
Opera
Safari
Node.js
PhantomJS (since it uses V8 like Chrome and Node.js)
and more, I'm sure. As long as you're debugging in any of the environments which supports it, you're fine. You should be removing your logging statements before pushing to production anyway so as long as it works for debugging, it's nothing to worry about.
So I have a fairly large Single-Page-Application based on Steve Sandersons SPA template. custom bindingHandlers, validation etc all working fine.
We require the use of the XMLHttpRequests, Session and Local storage as well as some other libraries that don't have universal support (jquery 2.0 etc). I have a core module which handles identity and exposes a few services and both of these are reliant on these features. This is loaded when the user first visits the page.
I have an issue with older browsers where either a) they don't support some of the modules being loaded so they throw an error before hitting the onload function, or b) it hits the onload function but they don't support the browser features so I need to raise an exception myself and handle it in some manner.
Example: IE8 throws an 'Object doesn't support property or method 'addEventListener'' (jquery error) and IE9 Doesn't support everything I need so I throw a custom error.
define('core', ['jquery', 'browser'], function($, browser) {
if(!browser.hasFullSupport) {
throw new Error('Update your browser');
}
// aload of gubbins that requires sessionStorage etc
return {
identity: identity,
serviceA: serviceA,
serviceB: serviceB
}
}, function(err) {
// doesn't catch the ie8 error here
});
I've tried setting a window.onerror but it works differently across browser versions and in some I can't capture the error message properly, I just get a 'Script Error'.
I know I can add an error event handler for the module definitions but it doesn't capture the errors i'm experiencing.
I've seen people use
requirejs.onError = function(err) {
// something here
}
but i'm using the requirejs gulp bundler and I can't see where this object would exposed (if it is at all)
var require = {
baseUrl: ".",
paths: {
"modernizr": "bower_modules/modernizr/modernizr",
"browser": "app/browser-detect",
"crossroads": "bower_modules/crossroads/dist/crossroads.min",
"hasher": "bower_modules/hasher/dist/js/hasher.min",
"jquery": "bower_modules/jquery/dist/jquery.min",
....
// gulpfile
var requireJsRuntimeConfig = vm.runInNewContext(fs.readFileSync('src/app/require.config.js') + '; require;');
requireJsOptimizerConfig = merge(requireJsRuntimeConfig, {
out: 'scripts.js',
baseUrl: './src',
name: 'app/startup',
paths: {
requireLib: 'bower_modules/requirejs/require'
},
include: [
'requireLib',
'components/nav-bar/nav-bar',
.....
gulp.task('js', function () {
return rjs(requireJsOptimizerConfig)
.pipe(uglify())
.pipe(gulp.dest('./dist/'));
});
There's loads of components/pages and each could throw an error, but it's this initial core component loading that i'm keen to sort out. I'd like to distinguish between errors (that may or may not be caused by the browser being too old) and between me detecting that they're too old before hand, is there an elegant way to achieve this using this template model?
I'd rather not deviate too far from the template as i'm not too familiar with requirejs / gulp etc but i'm open to suggestions.
You contradict yourself:
We require the use of the XMLHttpRequests, Session and Local storage as well as some other libraries that don't have universal support (jquery 2.0 etc)
But:
IE8 throws an 'Object doesn't support property or method 'addEventListener'' (jquery error) and IE9 Doesn't support everything I need so I throw a custom error.
You can't use libraries and HTML 5 features for newer browsers and expect older browsers to still work. Libraries that do not support legacy browsers like IE 8 do not fail gracefully so you cannot handle the failure very well. And even if you found a workaround to somehow circumvent the errors, you would still need to test them all in old browsers periodically which beats the intent to support only newer browsers.
So I recommend you two approaches:
Either decide not to support olders browsers at all and test the app only in newest modern browsers. You could use modern versions of libraries that dropped support of old browsers and not worry about old browsers at all. It depends on the state of your user base. Or:
Downgrade libraries to versions that support your minimal required browsers and continue developing the app with them. Test the app and fix all errors that occur in old browsers. Use polyfills that enable new HTML 5 features in old browsers via emulation.
Both firebug and the built in console in webkit browsers make it possible to set breakpoints in running Javascript code, so you can debug it as you would with any other language.
What I'm wondering is if there is any way that I can instruct firebug or webkit that I'd like to set a breakpoint on line X in file Y at runtime, and to be able to examine variables in the specific scope that I have paused in.
I need something that can work in both Chrome (or any other webkit browser) and Firefox. For the latter Firebug is an acceptable dependency. Supporting IE is not a requirement.
I've been building an in-browser IDE ( quick video for the interested: http://www.youtube.com/watch?v=c5lGwqi8L_g ) and want to give it a bit more meat.
One thing I did try was just adding debugger; as an extra line where users set them, but this isn't really an ideal solution.
I'd say you can definitely do this for webkit browsers using the remote debugging protocol. This is based on a websocket connection and a json message protocol that goes back and forth.
You can read the announcement and the whole protocol schema.
Chrome also offers more information about this inside its remote developer-tools docs.
For the debugger domain, for instance, you can see how you can use Debugger.setBreakpoint, Debugger.setBreakpointByUrl and Debugger.setBreakpointsActive to work with breakpoints.
On the other hand, Mozilla also seems to be working on this as you can see in https://developer.mozilla.org/en-US/docs/Tools/Debugger-API and https://wiki.mozilla.org/Remote_Debugging_Protocol though I don't know the completion status of it.
In this case, you can work with breakpoints using the Debugger.Script APIs setBreakPoint, getBreakPoint, getBreakpoints, clearBreakpoints and clearAllBreakpoints
I hope this helps you move forward.
There isn't such a thing, at least not using the public, scriptable side of JavaScript. It would be possible if you have a privileged browser extension that could do that for you. For example, Firebug has a debug method which you can call from its command line, but not from scripts inside a page.
So, you have two solutions:
Implement your own JavaScript interpreter, which you can control as you wish. Might be a bit too ambitious, though...
Rely on a browser extension that can set breakpoints anywhere in the code, expose some API to public code, and interact with it from your JavaScript. But that means that users will have to install some extra piece of software before they can use your "Web IDE".
Use _defineSetter__ to watch variables, and combine it with a call to debugger when an assignment happens.
__defineSetter__("name", function() { debugger; });
or defineProperty:
function setter () { debugger; }
Object.defineProperty(Math, 'name', { set: setter });
References
MDN: Object.defineProperty
A List Apart: Advanced Debugging With JavaScript
JavaScript Getters and Setters