dougwilson/nodejs-depd

Support the browser

bajtos opened this issue · 11 comments

I'd like to use depd in LoopBack, a project that supports both the server (Node.js) and the browser (via browserify).

There are two major problems why depd does not work in the browser now:

  • process.stderr is not available in the browser. index.js#L245-L250
  • Error.captureStackTrace is Chrome-specific and not available in all browsers (PhantomJS 1.x is a good example). index.js#L375

There are few minor details to work out too, but they can be IMO deferred until later:

  • Map process.env based configuration to a browser way. Possibly via localStorage as "debug" does (docs)?
  • The event emitter in node-process is implemented as a no-op, thus process.on('deprecation', fn) won't work now.

Yes, those are the easy ones :) The main pain point is how to do the repeat warning suppression and pointing to the caller, both of which are using call stack walking.

What's nice about this module is that it doesn't warn only on first call, but rather for each unique caller callsite + calle callsite. This allows the user to run their program and collect at the deprecated calls in a single go, which things like node.js core deprecate make impossible since they only warn on whatever the first call was.

Think I you are using a lib that calls a deprecated function. Then your code calls that deprecated function: since you can't change that other lib, you would like to know if your own stuff called the deprecated function.

So thinking of it more, there are a few main things we need to gather first:

  1. Exactly what browsers (and versions) should be supported.
  2. Determine how to set up automated testing for these
  3. Lean what browserify is and how to use it
  1. Exactly what browsers (and versions) should be supported.

From my POV, all evergreen browsers (Chrome, Firefox, Safari) and Internet Explorer 8+ (that's the difficult part).

  1. Determine how to set up automated testing for these

This should be pretty easy via https://ci.testling.com/, although I haven't used it myself yet.

  1. Lean what browserify is and how to use it

Here is a tutorial you may find useful: http://substack.net/how_I_write_tests_for_node_and_the_browser

The testling-ci docs makes me believe it should be very easy to setup the automated CI build: https://ci.testling.com/guide/mocha

Awesome, thank you for the information! I'll check it out. I'll likely start with just the browsers that support access to the raw JS call stack first, and then look into what is needed to actually get it to work without access to the call stack.

This module also requires support for Object.defineProperty and similar ES5 features, so that may limit the supported browser list.

This module also requires support for Object.defineProperty and similar ES5 features, so that may limit the supported browser list.

Is this required for all module users, or only when calling depd.property()?

I'll likely start with just the browsers that support access to the raw JS call stack first, and then look into what is needed to actually get it to work without access to the call stack.

From my POV, I would prefer an implementation that works across all browsers, even if it (initially) provided less features than the Node version.

However, since I don't have time to work on this feature myself, I should not complain either :)

There is also a problem if you use a Content Security Policy, because eval is disallowed (by default).

Angular.js for example detects an active CSP and uses a fallback in that case.
However, there seems to be no standard way to tell a module that a CSP is active. Angular.js uses a (data-)ng-csp attribute on the <html> element, but a global variable in JavaScript would also work. This part is not absolutely necessary though - it only avoids error messages caused by trying if eval works.

Interesting. Currently the reason for the eval is because we need to keep the function's arity intact.

Yes, I know, on stackoverflow there is no other way than eval/new Function (that supports an indefinite number of arguments).
The easier solution is just adding 'unsafe-eval' to the CSP, but of course that's not ideal.

@bajtos and others that are subscribed here, a new version of this module (1.1.0) is about to be released that adds support for web browsers via. Browserify/webpack by simply providing the API but in a "no-op mode". After that release, work will begin on bringing various features into the browser, but unless you really, really desire the features in the browser build of your module, you would be able to upgrade to 1.1.0 and remove any custom depd module overrides.

@dougwilson thank you for adding basic support for running the module via browserify. Since we have implemented a workaround that actually logs deprecation warnings (see browser.depd.js), I prefer to stick with that until depd prints warnings in the browser too.