Now that the context stores the active execution stack, and because
removeAsyncListener() always removed the AsyncListener from the queue
and the stack, there's no need to keep a stack around anymore. Instead
the active asyncQueue and the currentContext is able to handle it all.
Signed-off-by: Forrest L Norvell <ogd@aoaioxxysz.net>
Now that process.createAsyncListener() returns a unique object instance
it is no longer necessary to compare the uid's of the objects.
Signed-off-by: Timothy J Fontaine <tjfontaine@gmail.com>
It was possible that the same AL instance was run twice if it were both
attached to the currentContext then again added to the new asyncQueue
generated for the new stack.
Signed-off-by: Timothy J Fontaine <tjfontaine@gmail.com>
The ability to add/remove an AsyncListener to an object after its
creation was an artifact of trying to get AL working with the domain
module. Now that is no longer necessary and other features are going to
be implemented that would be affected by this functionality. So the code
will be removed for now to simplify the implementation process.
In the future this code will likely be reintroduced, but after some
other more important matters have been addressed.
None of this functionality was documented, as is was meant specifically
for domain specific implementation work arounds.
Signed-off-by: Timothy J Fontaine <tjfontaine@gmail.com>
Before when an AsyncListener object was created and the "create"
callback returned a value, it was necessary to construct a new Object
with the same callbacks but add a place for the new storage value.
Now, instead, a separate storage array is kept on the context which is
used for any return value of the "create" callback. This significantly
reduces the number of Objects that need to be created.
Also added a flags property to the context to quickly check if a
specific callback was available either on the context or on the
AsyncListener instance itself.
Few other minor changes for readability that were difficult to separate
into their own commit.
This has not been optimized yet.
This is a slightly modified revert of bc39bdd.
Getting domains to use AsyncListeners became too much of a challenge
with many edge cases. While this is still a goal, it will have to be
deferred for now until more test coverage can be provided.
Instead of checking the uid on the array index of the queue, instead the
object property "uid" was checked on the queue iteself. Because this
will always evaluate to "undefined" the same listener could be added
multiple times to the same context.
There was a flaw in the old API that has been fixed. Now the
asyncListener callback is now the "create" object property in the
callback object, and is optional.
The null signal test existed, but only tested the case where the target
process existed, not when it did not exist.
Also clarified that SIGUSR1 is reserved by Node.js only for receiveing,
its not at all reserved when sending a signal with kill().
kill(pid, 'O_RDWR'), or any other node constant, "worked". I fixed this
by also checking for 'SIG'. The same as done in the isSignal() function.
Now the signal names supported by process.kill() are the same as those
supported by process.on().
context._asyncQueue shouldn't be exposed as asyncQueue, as it allows
modification of queues already attached to an event. Which is not
supposed to happend. Instead context._asyncQueue should be copied.
Removing the depth counter while processing the nextTickQueue made it
possible to run out of memory if in an infinite recursive loop using
nextTick(). There was also an edge case where too many callbacks were
pushed onto the nextTickQueue, while not actually being recursive.
This is being done to prevent possible cryptic FATAL ERROR messages from
popping up, and issues being posted about them.
The domain module has been switched over to use the domain module API as
much as currently possible. There are still some hooks in the
EventEmitter, but hopefully we can remove those in the future.
AsyncListener is a JS API that works in tandem with the AsyncWrap class
to allow the user to be alerted to key events in the life cycle of an
asynchronous event. The AsyncWrap class has its own MakeCallback
implementation that core will be migrated to use, and uses state sharing
techniques to allow quicker communication between JS and C++ whether the
async event callbacks need to be called.
There was no need to share state between C++ and JS for these two
values. So they have been moved to their respective locations. This will
help performance only a tiny bit, but it does help code complexity much
more.
Since it is Unix tradition to use exit code 1 for general-purpose script
bail-out, and the way of doing that in Node is to throw an exception and
not catch it, it makes the most sense to exit with 1 when an exception
goes uncaught.
Move the `Invalid Argument` exit to 9, so that it's something specific,
and clear that it's a node internal error.
Also, document the exit codes that we use.
This commit makes it possible to use multiple V8 execution contexts
within a single event loop. Put another way, handle and request wrap
objects now "remember" the context they belong to and switch back to
that context when the time comes to call into JS land.
This could have been done in a quick and hacky way by calling
v8::Object::GetCreationContext() on the wrap object right before
making a callback but that leaves a fairly wide margin for bugs.
Instead, we make the context explicit through a new Environment class
that encapsulates everything (or almost everything) that belongs to
the context. Variables that used to be a static or a global are now
members of the aforementioned class. An additional benefit is that
this approach should make it relatively straightforward to add full
isolate support in due course.
There is no JavaScript API yet but that will be added in the near
future.
This work was graciously sponsored by GitHub, Inc.
This is useful when we need to push some debugging messages out to
stderr, without going through the Writable class, or triggering any kind
of nextTick or callback behavior.
Passing a filename is still supported in place of certain options
arguments, for backward-compatibility, but timeout and display-errors
are not translated since those were undocumented.
Also managed to eliminate an extra stack trace line by not calling
through the `createScript` export.
Added a few message tests to show how `displayErrors` works.
Instead of doing all the domain handling in core, allow the domain to
set an error handler that'll take care of it all. This way the domain
error handling can be abstracted enough for any user to use it.
As documented in #3042 and in [1], the existing vm implementation has
many problems. All of these are solved by @brianmcd's [contextify][2]
package. This commit uses contextify as a conceptual base and its code
core to overhaul the vm module and fix its many edge cases and caveats.
Functionally, this fixes#3042. In particular:
- A context is now indistinguishable from the object it is based on
(the "sandbox"). A context is simply a sandbox that has been marked
by the vm module, via `vm.createContext`, with special internal
information that allows scripts to be run inside of it.
- Consequently, items added to the context from anywhere are
immediately visible to all code that can access that context, both
inside and outside the virtual machine.
This commit also smooths over the API very slightly:
- Parameter defaults are now uniformly triggered via `undefined`, per
ES6 semantics and previous discussion at [3].
- Several undocumented and problematic features have been removed, e.g.
the conflation of `vm.Script` with `vm` itself, and the fact that
`Script` instances also had all static `vm` methods. The API is now
exactly as documented (although arguably the existence of the
`vm.Script` export is not yet documented, just the `Script` class
itself).
In terms of implementation, this replaces node_script.cc with
node_contextify.cc, which is derived originally from [4] (see [5]) but
has since undergone extensive modifications and iterations to expose
the most useful C++ API and use the coding conventions and utilities of
Node core.
The bindings exposed by `process.binding('contextify')`
(node_contextify.cc) replace those formerly exposed by
`process.binding('evals')` (node_script.cc). They are:
- ContextifyScript(code, [filename]), with methods:
- runInThisContext()
- runInContext(sandbox, [timeout])
- makeContext(sandbox)
From this, the vm.js file builds the entire documented vm module API.
node.js and module.js were modified to use this new native binding, or
the vm module itself where possible. This introduces an extra line or
two into the stack traces of module compilation (and thus into most
stack traces), explaining the changed tests.
The tests were also updated slightly, with all vm-related simple tests
consolidated as test/simple/test-vm-* (some of them were formerly
test/simple/test-script-*). At the same time they switched from
`common.debug` to `console.error` and were updated to use
`assert.throws` instead of rolling their own error-testing methods.
New tests were also added, of course, demonstrating the new
capabilities and fixes.
[1]: http://nodejs.org/docs/v0.10.16/api/vm.html#vm_caveats
[2]: https://github.com/brianmcd/contextify
[3]: https://github.com/joyent/node/issues/5323#issuecomment-20250726
[4]: bf123f3ef9/src/contextify.cc
[5]: https://gist.github.com/domenic/6068120
To prevent all unnecessary calls to JS from MakeCallback, the remaining
two immediate return variables inTick and lastThrew have been added to
infoBox. Now MakeCallback should never need to call into JS unless it
absolutely has to.
Also removed Tock. Performance tests showed it was at least as fast or
faster than using a normal object, and this is more readable.
Libuv now returns errors directly. Make everything in src/ and lib/
follow suit.
The changes to lib/ are not strictly necessary but they remove the need
for the abominations that are process._errno and node::SetErrno().
Memory allocations are now done through smalloc. The Buffer cc class has
been removed completely, but for backwards compatibility have left the
namespace as Buffer.
The .parent attribute is only set if the Buffer is a slice of an
allocation. Which is then set to the alloc object (not a Buffer).
The .offset attribute is now a ReadOnly set to 0, for backwards
compatibility. I'd like to remove it in the future (pre v1.0).
A few alterations have been made to how arguments are either coerced or
thrown. All primitives will now be coerced to their respective values,
and (most) all out of range index requests will throw.
The indexes that are coerced were left for backwards compatibility. For
example: Buffer slice operates more like Array slice, and coerces
instead of throwing out of range indexes. This may change in the future.
The reason for wanting to throw for out of range indexes is because
giving js access to raw memory has high potential risk. To mitigate that
it's easier to make sure the developer is always quickly alerted to the
fact that their code is attempting to access beyond memory bounds.
Because SlowBuffer will be deprecated, and simply returns a new Buffer
instance, all tests on SlowBuffer have been removed.
Heapdumps will now show usage under "smalloc" instead of "Buffer".
ParseArrayIndex was added to node_internals to support proper uint
argument checking/coercion for external array data indexes.
SlabAllocator had to be updated since handle_ no longer exists.
Remove the need to call start/stop the uv_idle spinner between
MakeCallbacks. The one place where the tick processor needs to be kicked
is where a user catches uncaughtException. For that we'll now use
setImmediate, which accomplishes the same task.
maxTickDepth checks have been removed for domains and replaced with a
flag that checks if the last callback threw. If it did then execution of
the remaining tickQueue is deferred to the spinner.
This is to prevent domains from entering a continuous loop when an error
callback also throws an error.
Removes the check for maxTickDepth for non-domain callbacks. So a user
can starve I/O by setting a recursive nextTick.
The domain case is more complex and will be addressed in another commit.
Add a watchdog class which executes a timer in a separate event loop in
a separate thread that will terminate v8 execution if it expires.
Add timeout argument to functions in vm module which use the watchdog
if a non-zero timeout is specified.
Since _tickCallback and _tickDomainCallback were both called from
MakeCallback, it was possible for a callback to be called that required
a domain directly to _tickCallback.
The fix was to implement process.usingDomains(). This will set all
applicable functions to their domain counterparts, and set a flag in cc
to let MakeCallback know domain callbacks always need to be checked.
Added test in own file. It's important that the test remains isolated.
This reverts commit ea1cba6246.
The offending commit was intended to land on the v0.8 branch only, but
it accidentally got merged at some point.
Closes#5054.
It's cleaner to only load domain ticker logic when the domains are being
used. This makes execution slightly quicker in both cases, and simpler
from the spinner since there is no need to check if the latest callback
requires use of domains.