dougwilson / nodejs-depd Goto Github PK
View Code? Open in Web Editor NEWDeprecate all the things
License: MIT License
Deprecate all the things
License: MIT License
If there is a call site that invokes multiple deprecated functions dynamically at the same site, the later calls at the same site to different functions will not warn.
I have no idea why this error occurs, have trouble pinpointing it down.
TypeError: Cannot redefine property: callSiteToString
at Function.defineProperty (<anonymous>)
at Object.get [as callSiteToString] (\path\to\project\node_modules\depd\lib\compat\index.js:57:12)
at Object.<anonymous> (\path\to\project\node_modules\depd\lib\compat\index.js)
I'm using those packages: koa, koa-router, std/esm and mongoose.
Recently my app keeps exploding because of this error from depd
:
./node_modules/depd/index.js:410
var deprecatedfn = eval('(function (' + args + ') {\n' +
^
TypeError: eval is not a function
I think node.js
removed eval()
completely in favor of VM
: https://nodejs.org/api/vm.html
depd
is a dep of a lot of modules in my case: express
, http-errors
, send
and body-parser
So, my question is why is depd v2.x not being released already to solve this mayhem properly?
When the number of stack frames in an error is under 3, depd
does not fail gracefully. I'm working on a framework that cleans up stack traces by hiding lines that are primarily boilerplate. In this process, this ends up at times with a stack trace that is small enough to cause this scenario.
Depd is a transitive dependency that I do not control, and so my application will break with imports failing almost seemingly without a pattern.
I'm happy to submit a PR. I'm thinking it should continue properly if it cannot retrieve stack information, but with just an unknown location.
eval
usage in this function disallows this to be used in Chrome Apps or Electron Apps like Atom Packages
The usage seems simple straight forward, that eval could be replaced by a closure
Since the deprecation warnings are simply written to stderr, they are not easy to instrument or intercept. An example would be a large system that wants to write all events to an external service but would like more structured messages than just stderr log lines. Possible interface:
process.on('deprecation', function ondeprecation(err) {
// err is an Error object representing the deprecation
// err.namespace
// err.stack
// err.message
console.log(err.stack)
})
If there are any deprecation listeners attached to process, then nothing is written to stderr.
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-L250Error.captureStackTrace
is Chrome-specific and not available in all browsers (PhantomJS 1.x is a good example). index.js#L375There are few minor details to work out too, but they can be IMO deferred until later:
process.env
based configuration to a browser way. Possibly via localStorage
as "debug" does (docs)?process.on('deprecation', fn)
won't work now.It would be nice to be able to silence certain namespaces, probably through an environment variable (like DEBUG
). Possible interface:
$ NO_DEPRECATION=my-module,other-module node my_script.js
Should this module honor Node.js core's --no-deprecation
argument to silence everything?
I do not wanna to check the property of the options whether exists, why not do this in depd?
deprecated.property(options, "prop")
//if isObject(options) && (options.prop) deprecated.property(options, "prop")
For when the module is installed, it would be nice if the stack tracing was node_modules
-aware, where if a dep uses a dep, perhaps the displayed location would be the first frame outside the node_modules
tree.
@dougwilson As promised in #27 here is the repro of the issue I am having. Use the with-esm
branch to see the issue.
The without-esm
branch is fine with importing sequelize, so maybe not worth seeing.
I tested with couple Node versions, v8.9.0 and v10.7.0, so I doubt the version matters there.
If OS default language is Turkish, some errors occur. More info and solution here.
depd/index.js:259
var file = callSite.getFileName() || '<anonymous>'
^
TypeError: Cannot call method 'getFileName' of undefined
at callSiteLocation (depd/index.js:259:23)
at Function.log (depd/index.js:201:12)
at deprecate (depd/index.js:124:9)
In v8, when rapidly calling Error.captureStackTrace
, an empty stack trace will end up being returned. This module needs to handle that case.
wanna be able to just do var str = callsite()
or something.
The following line in index.js can crash some node apps.
var basePath = process.cwd()
This line in index.js is problematic for some node applications that might get invoked from a directory that has been removed by another process.
The application may not actually need the current working directory, but it never gets a chance to run because node barfs if depd
is a dependency of anything pulled in with a requires
statement.
I haven't looked into why you need this, but maybe __filename
or __dirname
would be more appropriate here? Since it would be hard to execute a node app that didn't exist.
express
to your project, directly or indirectly, which adds depd
to your projectyarn run dev
On every code file change, the compiler spits out the following warning on the console:
Use of eval is strongly discouraged, as it poses security risks and may cause issues with minification
408:
409: // eslint-disable-next-line no-eval
410: var deprecatedfn = eval('(function (' + args + ') {\n' +
^
411: '"use strict"\n' +
412: 'log.call(deprecate, message, site)\n' +
This is due to depd
.
eval()
is not used at all. The error message is correct.
Hi,
I've opened a but on puppetexplorer but it seem the bug came from your module (I'm a noob in nodejs so perhaps I'm totally wrong)
I've got this error in Firefox "TypeError: Error.captureStackTrace is not a function"
If you check other nodejs module you have acode like this
if (Error.captureStackTrace) {
Error.captureStackTrace(this, stackStartFunction);
}
else {
// non v8 browsers so we can have a stacktrace
var err = new Error();
if (err.stack) {
var out = err.stack;
// try to strip useless frames
var fn_name = stackStartFunction.name;
var idx = out.indexOf('\n' + fn_name);
if (idx >= 0) {
// once we have located the function frame
// we need to strip out everything before it (and its line)
var next_line = out.indexOf('\n', idx + 1);
out = out.substring(next_line + 1);
}
this.stack = out;
}
}
Can be realized by setting strict mode in test/fixtures/my-lib
.
From the API docs:
To maintain restrictions imposed on strict mode functions, frames that have a strict mode function and all frames below (its caller etc.) are not allow to access their receiver and function objects.
Failing test:
1) deprecate(message) when message omitted should generate message for function call on named function: TypeError: Cannot read property 'constructor' of undefined at CallSiteGetTypeName (native) at defaultMessage (/Users/jsisk/src/node/nodejs-depd/index.js:283:27) at Function.log (/Users/jsisk/src/node/nodejs-depd/index.js:234:9) at deprecate (/Users/jsisk/src/node/nodejs-depd/index.js:125:9) at automsgnamed (/Users/jsisk/src/node/nodejs-depd/test/fixtures/my-lib.js:59:3) at callold (/Users/jsisk/src/node/nodejs-depd/test/test.js:116:9) at captureStderr (/Users/jsisk/src/node/nodejs-depd/test/test.js:664:5) at Context.<anonymous> (/Users/jsisk/src/node/nodejs-depd/test/test.js:118:20) at callFn (/Users/jsisk/src/node/nodejs-depd/node_modules/mocha/lib/runnable.js:250:21) at Test.Runnable.run (/Users/jsisk/src/node/nodejs-depd/node_modules/mocha/lib/runnable.js:243:7) at Runner.runTest (/Users/jsisk/src/node/nodejs-depd/node_modules/mocha/lib/runner.js:373:10) at /Users/jsisk/src/node/nodejs-depd/node_modules/mocha/lib/runner.js:451:12 at next (/Users/jsisk/src/node/nodejs-depd/node_modules/mocha/lib/runner.js:298:14) at /Users/jsisk/src/node/nodejs-depd/node_modules/mocha/lib/runner.js:308:7 at next (/Users/jsisk/src/node/nodejs-depd/node_modules/mocha/lib/runner.js:246:23) at Immediate._onImmediate (/Users/jsisk/src/node/nodejs-depd/node_modules/mocha/lib/runner.js:275:5) at processImmediate [as _immediateCallback] (timers.js:358:17)
is eval really needed?
(!) Use of eval is strongly discouraged
https://rollupjs.org/guide/en/#avoiding-eval
node_modules/depd/index.js
413:
414: // eslint-disable-next-line no-eval
415: var deprecatedfn = eval('(function (' + args + ') {\n' +
^
416: '"use strict"\n' +
417: 'log.call(deprecate, message, site)\n' +
created deploy/bundle.js in 2.8s
egg deprecated ctx.isAjax is deprecated internal/process/next_tick.js:103:7
Is there no way to avoid this function?
function getStack () {
var limit = Error.stackTraceLimit
var obj = {}
var prep = Error.prepareStackTrace
Error.prepareStackTrace = prepareObjectStackTrace
Error.stackTraceLimit = Math.max(10, limit)
// capture the stack
Error.captureStackTrace(obj)
// slice this function off the top
var stack = obj.stack.slice(1)
Error.prepareStackTrace = prep
Error.stackTraceLimit = limit
return stack
}
More specifically the native Error
type overwrites.
I'm not against overwrites to native types but this sort of unrequested overwrite is just annoying. Overwrites are either at the user level or by request if libraries offer them (usually the case for unit test libraries).
What happens with cases such as this particular case is that it (no surprise) bumps heads with other requested overwrites resulting in hard to track errors such as callSite.getFileName is not a function
. Since this included by things such as body-parser, you are forcing this overwrite on everyone who uses it.
In addition the apis used there, seem to be V8 specific, throwing even more spanners around.
$ node --frozen-intrinsics
> require('depd')('http-errors')('non-error status code; use only 4xx or 5xx status codes')
Uncaught:
TypeError <Object <Object <[Object: null prototype] {}>>>: callSite.getFileName is not a function
Until #16 is implemented, please please can we at least have graceful failure when running in unsupported browsers?
I don't mind whether you want to print a warning every time, never print a warning, or use console.error
, but I would like the rest of my code to run. At the moment depd blows up with an exception and everything stops :(
In reference to #14, defining a fallback isn't a good solution at all:
depd
does non-standard things, not meThanks.
Add a convenience method to created a wrapped property that just deprecates all calls to the property. Possible interface:
var deprecate = requrie('depd')('my-cool-module')
var obj = {
thing: true
}
deprecate.property(obj, 'thing', 'oldobj.thing')
exports.oldobj= obj
Add a convenience method to created a wrapped function that just deprecates all calls to the function (needs to preserve function arity). Possible interface:
var deprecate = requrie('depd')('my-cool-module')
exports.oldfunction = deprecate.function(oldfunction, 'oldfunction')
function oldfunction() {}
It would be nice, when tracking down deprecations manually, to see the full stack of the deprecation's call site. Possible Interface:
$ TRACE_DEPRECATION=* node my_script.js
my-module deprecated oldfunction
at Object.<anonymous> ([eval]-wrapper:6:22)
at Module._compile (module.js:456:26)
at evalScript (node.js:532:25)
at startup (node.js:80:7)
at node.js:902:3
Can probably honor Node.js core's --trace-deprecation
flag as well.
This package causes applications to fail to start if using NodeJS's --disallow-code-generation-from-strings
security option, even if the application is not using a deprecated function, due to the use of dynamically generated code:
Line 425 in 73364d0
This could be fixed in multiple ways:
EvalError
exception which gets thrown in this environment and fall-back to a simpler alternative; orEvalError
and fall-back to a pass-through (just return fn
unchanged), since warning about deprecated functions seems more useful at dev-time than in production anyway.Since this package is being used by express
, it seems especially useful to be able to run with additional security options enabled. This is the only change needed to let express
run with --disallow-code-generation-from-strings
.
Sometimes a project may be so big, that even a deprecation cycle still might not be enough; after the next major that removes the feature it may be useful to have a "removed" message for some things that used to be deprecated.
I'm thinking perhaps add a remove
property to deprecate
:
var deprecate = require('depd')('my-module')
exports.missingfn = deprecate.remove.function('missingfn')
The function
, property
and other helpers would not wrap things, since they are meant for removed things (thus, what would you be wrapping?).
It took me ages to realise why I couldn't silence some deprecation warnings using process.noDeprecation
- The deprecation was coming from depd
instead of regular Node.js util
and apparently the standard flag is not respected.
I noticed that when I wrapped a function in deprecate.function()
in my library, my benchmarks took a big hit, dropping ~62%. Changing my use to be an empty function with deprecate()
inside brought my speed back to normal.
The important part: this slow down occured even without that function be executed. It simply existing slow things down.
Looking in the source, it looks like the goal is to keep the arity the same. Did you find changing the arity for a deprecated function caused programs to break? I'd vote for not worrying about it.
However, if it is a big deal, then I'd suggest instead having several wrapArity1(fn)
, wrapArity2(fn)
, and so forth, up to... 6? 10? It could be small as well.
Hey @dougwilson, I was wondering if you'd be willing to work with me to figure out a way to make this compatible with Node.js' source-map support, we just landed an API for this here:
What I'd love would be to have a well defined way that we can expose transpiled stack traces to express users.
Try:
node -e "require('depd')('x')()" --enable-source-maps
It catch:
C:\workspace\node_modules\depd\index.js:268
var file = callSite.getFileName() || '<anonymous>'
^
TypeError: callSite.getFileName is not a function
at callSiteLocation (C:\workspace\npm-server\node_modules\depd\index.js:268:23)
at depd (C:\workspace\npm-server\node_modules\depd\index.js:109:14)
at [eval]:1:16
While experiment with the snapshot-blob feature of NodeJs I encountering an error during the snapshot build caused by the library:
var file = callSite.getFileName() || "<anonymous>";
^
TypeError: Cannot read properties of undefined (reading 'getFileName')
Apply the PR #48 fixes the issue, and allows me to create the blob.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.