summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Noordhuis <info@bnoordhuis.nl>2012-01-02 12:29:39 +0100
committerBen Noordhuis <info@bnoordhuis.nl>2012-01-02 12:29:39 +0100
commitc123ac05dc37311d3dfb37ed6f22baef58280379 (patch)
treef1c49f60d3affab2148d50af7df46c0fe2238c4d
parent4b3824b6826db3487d7490283d3d7f396720f337 (diff)
parent6f8839d2ac362ced42235a34a023af5e2c656501 (diff)
downloadnode-new-c123ac05dc37311d3dfb37ed6f22baef58280379.tar.gz
Merge remote-tracking branch 'origin/v0.6'
Conflicts: src/udp_wrap.cc
-rw-r--r--benchmark/http_simple.js6
-rw-r--r--deps/uv/LICENSE2
-rw-r--r--deps/uv/include/uv-private/uv-win.h2
-rw-r--r--deps/uv/src/unix/kqueue.c2
-rw-r--r--deps/uv/src/unix/linux.c2
-rw-r--r--deps/uv/src/unix/sunos.c2
-rw-r--r--deps/uv/src/win/fs-event.c145
-rw-r--r--deps/uv/src/win/fs.c8
-rw-r--r--deps/uv/test/test-fs-event.c20
-rw-r--r--deps/uv/test/test-fs.c68
-rw-r--r--deps/uv/test/test-list.h4
-rw-r--r--doc/api/http.markdown2
-rw-r--r--doc/community/index.html4
-rw-r--r--lib/repl.js18
-rw-r--r--src/node_crypto.cc27
-rw-r--r--src/node_crypto.h1
-rw-r--r--src/udp_wrap.cc1
-rw-r--r--test/simple/test-fs-watch.js18
-rw-r--r--test/simple/test-http-parser-bad-ref.js72
19 files changed, 346 insertions, 58 deletions
diff --git a/benchmark/http_simple.js b/benchmark/http_simple.js
index 4b550283b8..74ba4d7768 100644
--- a/benchmark/http_simple.js
+++ b/benchmark/http_simple.js
@@ -54,6 +54,12 @@ var server = http.createServer(function (req, res) {
} else if (command == "fixed") {
body = fixed;
+ } else if (command == "echo") {
+ res.writeHead(200, { "Content-Type": "text/plain",
+ "Transfer-Encoding": "chunked" });
+ req.pipe(res);
+ return;
+
} else {
status = 404;
body = "not found\n";
diff --git a/deps/uv/LICENSE b/deps/uv/LICENSE
index f7df47f71c..f62d7f1991 100644
--- a/deps/uv/LICENSE
+++ b/deps/uv/LICENSE
@@ -33,6 +33,8 @@ The externally maintained libraries used by libuv are:
- ngx_queue.h (from Nginx), copyright Igor Sysoev. Two clause BSD license.
+ - c-ares, copyright Daniel Stenberg and others. MIT licensed.
+
- libev, located at ev/ is copyright Marc Alexander Lehmann, and
dual-licensed under the MIT license and GPL2.
diff --git a/deps/uv/include/uv-private/uv-win.h b/deps/uv/include/uv-private/uv-win.h
index b4b89096d0..9e41fde6df 100644
--- a/deps/uv/include/uv-private/uv-win.h
+++ b/deps/uv/include/uv-private/uv-win.h
@@ -439,7 +439,7 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
uv_fs_event_cb cb; \
wchar_t* filew; \
wchar_t* short_filew; \
- int is_path_dir; \
+ wchar_t* dirw; \
char* buffer;
int uv_utf16_to_utf8(const wchar_t* utf16Buffer, size_t utf16Size,
diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c
index 551bce0a62..58a6816d8a 100644
--- a/deps/uv/src/unix/kqueue.c
+++ b/deps/uv/src/unix/kqueue.c
@@ -43,10 +43,12 @@ static void uv__fs_event_start(uv_fs_event_t* handle) {
handle->fd,
EV_LIBUV_KQUEUE_HACK);
ev_io_start(handle->loop->ev, &handle->event_watcher);
+ ev_unref(handle->loop->ev);
}
static void uv__fs_event_stop(uv_fs_event_t* handle) {
+ ev_ref(handle->loop->ev);
ev_io_stop(handle->loop->ev, &handle->event_watcher);
}
diff --git a/deps/uv/src/unix/linux.c b/deps/uv/src/unix/linux.c
index 17e06741ae..12473596eb 100644
--- a/deps/uv/src/unix/linux.c
+++ b/deps/uv/src/unix/linux.c
@@ -650,12 +650,14 @@ int uv_fs_event_init(uv_loop_t* loop,
ev_io_init(&handle->read_watcher, uv__inotify_read, fd, EV_READ);
ev_io_start(loop->ev, &handle->read_watcher);
+ ev_unref(loop->ev);
return 0;
}
void uv__fs_event_destroy(uv_fs_event_t* handle) {
+ ev_ref(handle->loop->ev);
ev_io_stop(handle->loop->ev, &handle->read_watcher);
uv__close(handle->fd);
handle->fd = -1;
diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c
index 0fd4e42f08..49d372b495 100644
--- a/deps/uv/src/unix/sunos.c
+++ b/deps/uv/src/unix/sunos.c
@@ -184,12 +184,14 @@ int uv_fs_event_init(uv_loop_t* loop,
ev_io_init(&handle->event_watcher, uv__fs_event_read, portfd, EV_READ);
ev_io_start(loop->ev, &handle->event_watcher);
+ ev_unref(loop->ev);
return 0;
}
void uv__fs_event_destroy(uv_fs_event_t* handle) {
+ ev_ref(handle->loop->ev);
ev_io_stop(handle->loop->ev, &handle->event_watcher);
uv__close(handle->fd);
handle->fd = -1;
diff --git a/deps/uv/src/win/fs-event.c b/deps/uv/src/win/fs-event.c
index b2f6583a40..5a25e9d647 100644
--- a/deps/uv/src/win/fs-event.c
+++ b/deps/uv/src/win/fs-event.c
@@ -22,6 +22,7 @@
#include <assert.h>
#include <malloc.h>
#include <errno.h>
+#include <stdio.h>
#include <string.h>
#include "uv.h"
#include "internal.h"
@@ -36,12 +37,12 @@ static void uv_fs_event_init_handle(uv_loop_t* loop, uv_fs_event_t* handle,
handle->loop = loop;
handle->flags = 0;
handle->cb = cb;
- handle->is_path_dir = 0;
handle->dir_handle = INVALID_HANDLE_VALUE;
handle->buffer = NULL;
handle->req_pending = 0;
handle->filew = NULL;
handle->short_filew = NULL;
+ handle->dirw = NULL;
uv_req_init(loop, (uv_req_t*)&handle->req);
handle->req.type = UV_FS_EVENT_REQ;
@@ -134,9 +135,9 @@ static int uv_split_path(const wchar_t* filename, wchar_t** dir,
int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle,
const char* filename, uv_fs_event_cb cb, int flags) {
- int name_size;
+ int name_size, is_path_dir;
DWORD attr, last_error;
- wchar_t* dir = NULL, *dir_to_watch, *filenamew;
+ wchar_t* dir = NULL, *dir_to_watch, *filenamew = NULL;
wchar_t short_path[MAX_PATH];
/* We don't support any flags yet. */
@@ -164,10 +165,11 @@ int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle,
goto error;
}
- handle->is_path_dir = (attr & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0;
+ is_path_dir = (attr & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0;
- if (handle->is_path_dir) {
+ if (is_path_dir) {
/* filename is a directory, so that's the directory that we will watch. */
+ handle->dirw = filenamew;
dir_to_watch = filenamew;
} else {
/*
@@ -192,6 +194,8 @@ int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle,
}
dir_to_watch = dir;
+ free(filenamew);
+ filenamew = NULL;
}
handle->dir_handle = CreateFileW(dir_to_watch,
@@ -268,6 +272,8 @@ error:
handle->short_filew = NULL;
}
+ free(filenamew);
+
if (handle->dir_handle != INVALID_HANDLE_VALUE) {
CloseHandle(handle->dir_handle);
handle->dir_handle = INVALID_HANDLE_VALUE;
@@ -286,8 +292,9 @@ error:
void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
uv_fs_event_t* handle) {
FILE_NOTIFY_INFORMATION* file_info;
+ int sizew, size, result;
char* filename = NULL;
- int utf8size;
+ wchar_t* filenamew, *long_filenamew = NULL;
DWORD offset = 0;
assert(req->type == UV_FS_EVENT_REQ);
@@ -300,39 +307,114 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
if (req->overlapped.InternalHigh > 0) {
do {
file_info = (FILE_NOTIFY_INFORMATION*)((char*)file_info + offset);
+ assert(!filename);
+ assert(!long_filenamew);
/*
* Fire the event only if we were asked to watch a directory,
* or if the filename filter matches.
*/
- if (handle->is_path_dir ||
+ if (handle->dirw ||
_wcsnicmp(handle->filew, file_info->FileName,
file_info->FileNameLength / sizeof(wchar_t)) == 0 ||
_wcsnicmp(handle->short_filew, file_info->FileName,
file_info->FileNameLength / sizeof(wchar_t)) == 0) {
-
- /* Convert the filename to utf8. */
- utf8size = uv_utf16_to_utf8(file_info->FileName,
- file_info->FileNameLength /
- sizeof(wchar_t),
- NULL,
- 0);
- if (utf8size) {
- filename = (char*)malloc(utf8size + 1);
- if (!filename) {
- uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
- }
- utf8size = uv_utf16_to_utf8(file_info->FileName,
- file_info->FileNameLength /
- sizeof(wchar_t),
- filename,
- utf8size);
- if (utf8size) {
- filename[utf8size] = '\0';
+ if (handle->dirw) {
+ /*
+ * We attempt to convert the file name to its long form for
+ * events that still point to valid files on disk.
+ * For removed and renamed events, we do not provide the file name.
+ */
+ if (file_info->Action != FILE_ACTION_REMOVED &&
+ file_info->Action != FILE_ACTION_RENAMED_OLD_NAME) {
+ /* Construct a full path to the file. */
+ size = wcslen(handle->dirw) +
+ file_info->FileNameLength / sizeof(wchar_t) + 2;
+
+ filenamew = (wchar_t*)malloc(size * sizeof(wchar_t));
+ if (!filenamew) {
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ }
+
+ _snwprintf(filenamew, size, L"%s\\%s", handle->dirw,
+ file_info->FileName);
+
+ filenamew[size - 1] = L'\0';
+
+ /* Convert to long name. */
+ size = GetLongPathNameW(filenamew, NULL, 0);
+
+ if (size) {
+ long_filenamew = (wchar_t*)malloc(size * sizeof(wchar_t));
+ if (!long_filenamew) {
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ }
+
+ size = GetLongPathNameW(filenamew, long_filenamew, size);
+ if (size) {
+ long_filenamew[size] = '\0';
+ } else {
+ free(long_filenamew);
+ long_filenamew = NULL;
+ }
+ }
+
+ free(filenamew);
+
+ if (long_filenamew) {
+ /* Get the file name out of the long path. */
+ result = uv_split_path(long_filenamew, NULL, &filenamew);
+ free(long_filenamew);
+
+ if (result == 0) {
+ long_filenamew = filenamew;
+ sizew = -1;
+ } else {
+ long_filenamew = NULL;
+ }
+ }
+
+ /*
+ * If we couldn't get the long name - just use the name
+ * provided by ReadDirectoryChangesW.
+ */
+ if (!long_filenamew) {
+ filenamew = file_info->FileName;
+ sizew = file_info->FileNameLength / sizeof(wchar_t);
+ }
} else {
- free(filename);
- filename = NULL;
+ /* Removed or renamed callbacks don't provide filename. */
+ filenamew = NULL;
+ }
+ } else {
+ /* We already have the long name of the file, so just use it. */
+ filenamew = handle->filew;
+ sizew = -1;
+ }
+
+ if (filenamew) {
+ /* Convert the filename to utf8. */
+ size = uv_utf16_to_utf8(filenamew,
+ sizew,
+ NULL,
+ 0);
+ if (size) {
+ filename = (char*)malloc(size + 1);
+ if (!filename) {
+ uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ }
+
+ size = uv_utf16_to_utf8(filenamew,
+ sizew,
+ filename,
+ size);
+ if (size) {
+ filename[size] = '\0';
+ } else {
+ free(filename);
+ filename = NULL;
+ }
}
}
@@ -351,6 +433,8 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
free(filename);
filename = NULL;
+ free(long_filenamew);
+ long_filenamew = NULL;
}
offset = file_info->NextEntryOffset;
@@ -411,6 +495,11 @@ void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle) {
handle->filename = NULL;
}
+ if (handle->dirw) {
+ free(handle->dirw);
+ handle->dirw = NULL;
+ }
+
if (handle->close_cb) {
handle->close_cb((uv_handle_t*)handle);
}
diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c
index 2037ddd6b7..78ccffab6b 100644
--- a/deps/uv/src/win/fs.c
+++ b/deps/uv/src/win/fs.c
@@ -542,8 +542,12 @@ void fs__fstat(uv_fs_t* req, uv_file file) {
void fs__rename(uv_fs_t* req, const wchar_t* path, const wchar_t* new_path) {
- int result = _wrename(path, new_path);
- SET_REQ_RESULT(req, result);
+ if (!MoveFileExW(path, new_path, MOVEFILE_REPLACE_EXISTING)) {
+ SET_REQ_RESULT_WIN32_ERROR(req, GetLastError());
+ return;
+ }
+
+ SET_REQ_RESULT(req, 0);
}
diff --git a/deps/uv/test/test-fs-event.c b/deps/uv/test/test-fs-event.c
index 9e169caae0..97d91ee3ec 100644
--- a/deps/uv/test/test-fs-event.c
+++ b/deps/uv/test/test-fs-event.c
@@ -302,7 +302,7 @@ static void timer_cb(uv_timer_t* handle, int status) {
ASSERT(status == 0);
r = uv_fs_event_init(handle->loop, &fs_event, ".", fs_event_fail, 0);
- ASSERT(r != -1);
+ ASSERT(r == 0);
uv_close((uv_handle_t*)&fs_event, close_cb);
uv_close((uv_handle_t*)handle, close_cb);
@@ -328,3 +328,21 @@ TEST_IMPL(fs_event_immediate_close) {
return 0;
}
+
+
+TEST_IMPL(fs_event_unref) {
+ uv_loop_t* loop;
+ int r;
+
+ loop = uv_default_loop();
+
+ r = uv_fs_event_init(loop, &fs_event, ".", fs_event_fail, 0);
+ ASSERT(r == 0);
+
+ uv_unref(loop);
+
+ r = uv_run(loop);
+ ASSERT(r == 0);
+
+ return 0;
+}
diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c
index 34f891c177..763af8a78d 100644
--- a/deps/uv/test/test-fs.c
+++ b/deps/uv/test/test-fs.c
@@ -1476,3 +1476,71 @@ TEST_IMPL(fs_file_open_append) {
return 0;
}
+
+
+TEST_IMPL(fs_rename_to_existing_file) {
+ int r;
+
+ /* Setup. */
+ unlink("test_file");
+ unlink("test_file2");
+
+ loop = uv_default_loop();
+
+ r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT,
+ S_IWRITE | S_IREAD, NULL);
+ ASSERT(r != -1);
+ ASSERT(open_req1.result != -1);
+ uv_fs_req_cleanup(&open_req1);
+
+ r = uv_fs_write(loop, &write_req, open_req1.result, test_buf,
+ sizeof(test_buf), -1, NULL);
+ ASSERT(r != -1);
+ ASSERT(write_req.result != -1);
+ uv_fs_req_cleanup(&write_req);
+
+ r = uv_fs_close(loop, &close_req, open_req1.result, NULL);
+ ASSERT(r != -1);
+ ASSERT(close_req.result != -1);
+ uv_fs_req_cleanup(&close_req);
+
+ r = uv_fs_open(loop, &open_req1, "test_file2", O_WRONLY | O_CREAT,
+ S_IWRITE | S_IREAD, NULL);
+ ASSERT(r != -1);
+ ASSERT(open_req1.result != -1);
+ uv_fs_req_cleanup(&open_req1);
+
+ r = uv_fs_close(loop, &close_req, open_req1.result, NULL);
+ ASSERT(r != -1);
+ ASSERT(close_req.result != -1);
+ uv_fs_req_cleanup(&close_req);
+
+ r = uv_fs_rename(loop, &rename_req, "test_file", "test_file2", NULL);
+ ASSERT(r != -1);
+ ASSERT(rename_req.result != -1);
+ uv_fs_req_cleanup(&rename_req);
+
+ r = uv_fs_open(loop, &open_req1, "test_file2", O_RDONLY, 0, NULL);
+ ASSERT(r != -1);
+ ASSERT(open_req1.result != -1);
+ uv_fs_req_cleanup(&open_req1);
+
+ memset(buf, 0, sizeof(buf));
+ r = uv_fs_read(loop, &read_req, open_req1.result, buf, sizeof(buf), -1,
+ NULL);
+ ASSERT(r != -1);
+ ASSERT(read_req.result != -1);
+ ASSERT(strcmp(buf, test_buf) == 0);
+ uv_fs_req_cleanup(&read_req);
+
+ r = uv_fs_close(loop, &close_req, open_req1.result, NULL);
+ ASSERT(r != -1);
+ ASSERT(close_req.result != -1);
+ uv_fs_req_cleanup(&close_req);
+
+ /* Cleanup */
+ unlink("test_file");
+ unlink("test_file2");
+
+ return 0;
+} \ No newline at end of file
diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h
index f5f0541269..4fcc055e12 100644
--- a/deps/uv/test/test-list.h
+++ b/deps/uv/test/test-list.h
@@ -115,9 +115,11 @@ TEST_DECLARE (fs_event_watch_file)
TEST_DECLARE (fs_event_watch_file_current_dir)
TEST_DECLARE (fs_event_no_callback_on_close)
TEST_DECLARE (fs_event_immediate_close)
+TEST_DECLARE (fs_event_unref)
TEST_DECLARE (fs_readdir_empty_dir)
TEST_DECLARE (fs_readdir_file)
TEST_DECLARE (fs_open_dir)
+TEST_DECLARE (fs_rename_to_existing_file)
TEST_DECLARE (threadpool_queue_work_simple)
TEST_DECLARE (threadpool_multiple_event_loops)
TEST_DECLARE (thread_mutex)
@@ -282,9 +284,11 @@ TASK_LIST_START
TEST_ENTRY (fs_event_watch_file_current_dir)
TEST_ENTRY (fs_event_no_callback_on_close)
TEST_ENTRY (fs_event_immediate_close)
+ TEST_ENTRY (fs_event_unref)
TEST_ENTRY (fs_readdir_empty_dir)
TEST_ENTRY (fs_readdir_file)
TEST_ENTRY (fs_open_dir)
+ TEST_ENTRY (fs_rename_to_existing_file)
TEST_ENTRY (threadpool_queue_work_simple)
TEST_ENTRY (threadpool_multiple_event_loops)
TEST_ENTRY (thread_mutex)
diff --git a/doc/api/http.markdown b/doc/api/http.markdown
index 8dd9935a1e..57f13a48ad 100644
--- a/doc/api/http.markdown
+++ b/doc/api/http.markdown
@@ -647,7 +647,7 @@ A client server pair that show you how to listen for the `upgrade` event using `
### Event: 'continue'
-`function ()`
+`function () { }`
Emitted when the server sends a '100 Continue' HTTP response, usually because
the request contained 'Expect: 100-continue'. This is an instruction that
diff --git a/doc/community/index.html b/doc/community/index.html
index 9c427624b5..dec8b58b90 100644
--- a/doc/community/index.html
+++ b/doc/community/index.html
@@ -73,7 +73,7 @@
should be reported to <a
href="https://github.com/joyent/node/issues">https://github.com/joyent/node/issues</a>.
Fixes to the code are welcome! Please see our <a
- href="https://github.com/joyent/node/wiki/Contributing">contirbuting
+ href="https://github.com/joyent/node/wiki/Contributing">contributing
guidelines</a> for information on how to submit a
patch.</p>
@@ -159,4 +159,4 @@
} catch(err) {}
</script>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/lib/repl.js b/lib/repl.js
index 2c3baeba28..b241164296 100644
--- a/lib/repl.js
+++ b/lib/repl.js
@@ -247,8 +247,8 @@ exports.REPLServer = REPLServer;
// prompt is a string to print on each line for the prompt,
// source is a stream to use for I/O, defaulting to stdin/stdout.
-exports.start = function(prompt, source, eval, useGlobal) {
- var repl = new REPLServer(prompt, source, eval, useGlobal);
+exports.start = function(prompt, source, eval, useGlobal, ignoreUndefined) {
+ var repl = new REPLServer(prompt, source, eval, useGlobal, ignoreUndefined);
if (!exports.repl) exports.repl = repl;
return repl;
};
@@ -712,12 +712,20 @@ function defineDefaultCommands(repl) {
}
});
+ var clearMessage;
+ if (repl.useGlobal) {
+ clearMessage = 'Alias for .break';
+ } else {
+ clearMessage = 'Break, and also clear the local context';
+ }
repl.defineCommand('clear', {
- help: 'Break, and also clear the local context',
+ help: clearMessage,
action: function() {
- this.outputStream.write('Clearing context...\n');
this.bufferedCommand = '';
- this.resetContext(true);
+ if (!this.useGlobal) {
+ this.outputStream.write('Clearing context...\n');
+ this.resetContext(true);
+ }
this.displayPrompt();
}
});
diff --git a/src/node_crypto.cc b/src/node_crypto.cc
index bcd3949ec0..5f58240e00 100644
--- a/src/node_crypto.cc
+++ b/src/node_crypto.cc
@@ -151,6 +151,7 @@ void SecureContext::Initialize(Handle<Object> target) {
NODE_SET_PROTOTYPE_METHOD(t, "addRootCerts", SecureContext::AddRootCerts);
NODE_SET_PROTOTYPE_METHOD(t, "setCiphers", SecureContext::SetCiphers);
NODE_SET_PROTOTYPE_METHOD(t, "setOptions", SecureContext::SetOptions);
+ NODE_SET_PROTOTYPE_METHOD(t, "clearOptions", SecureContext::ClearOptions);
NODE_SET_PROTOTYPE_METHOD(t, "setSessionIdContext",
SecureContext::SetSessionIdContext);
NODE_SET_PROTOTYPE_METHOD(t, "close", SecureContext::Close);
@@ -525,21 +526,23 @@ Handle<Value> SecureContext::SetCiphers(const Arguments& args) {
return True();
}
-Handle<Value> SecureContext::SetOptions(const Arguments& args) {
- HandleScope scope;
-
- SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.Holder());
-
- if (args.Length() != 1 || !args[0]->IsUint32()) {
- return ThrowException(Exception::TypeError(String::New("Bad parameter")));
+#define X(name, fn) \
+ Handle<Value> name(const Arguments& args) { \
+ HandleScope scope; \
+ SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.Holder()); \
+ if (args.Length() != 1 || !args[0]->IsInt32()) { \
+ return ThrowException( \
+ Exception::TypeError(String::New("Bad parameter"))); \
+ } \
+ fn(sc->ctx_, args[0]->Int32Value()); \
+ return True(); \
}
- unsigned int opts = args[0]->Uint32Value();
-
- SSL_CTX_set_options(sc->ctx_, opts);
+// can't use templates, SSL_CTX_set_options and SSL_CTX_clear_options are macros
+X(SecureContext::SetOptions, SSL_CTX_set_options)
+X(SecureContext::ClearOptions, SSL_CTX_clear_options)
- return True();
-}
+#undef X
Handle<Value> SecureContext::SetSessionIdContext(const Arguments& args) {
HandleScope scope;
diff --git a/src/node_crypto.h b/src/node_crypto.h
index 4cde964da4..58168e3df1 100644
--- a/src/node_crypto.h
+++ b/src/node_crypto.h
@@ -66,6 +66,7 @@ class SecureContext : ObjectWrap {
static v8::Handle<v8::Value> AddRootCerts(const v8::Arguments& args);
static v8::Handle<v8::Value> SetCiphers(const v8::Arguments& args);
static v8::Handle<v8::Value> SetOptions(const v8::Arguments& args);
+ static v8::Handle<v8::Value> ClearOptions(const v8::Arguments& args);
static v8::Handle<v8::Value> SetSessionIdContext(const v8::Arguments& args);
static v8::Handle<v8::Value> Close(const v8::Arguments& args);
diff --git a/src/udp_wrap.cc b/src/udp_wrap.cc
index dce45ada49..a6b7649e43 100644
--- a/src/udp_wrap.cc
+++ b/src/udp_wrap.cc
@@ -366,6 +366,7 @@ void UDPWrap::OnRecv(uv_udp_t* handle,
if (nread == -1) {
SetErrno(uv_last_error(Loop()));
+ ReleaseMemory(buf.base, NULL);
}
else {
Local<Object> rinfo = Object::New();
diff --git a/test/simple/test-fs-watch.js b/test/simple/test-fs-watch.js
index 989c6352f3..21fe3102e1 100644
--- a/test/simple/test-fs-watch.js
+++ b/test/simple/test-fs-watch.js
@@ -30,8 +30,7 @@ var watchSeenOne = 0;
var watchSeenTwo = 0;
var watchSeenThree = 0;
-var startDir = process.cwd();
-var testDir = common.fixturesDir;
+var testDir = common.tmpDir;
var filenameOne = 'watch.txt';
var filepathOne = path.join(testDir, filenameOne);
@@ -46,15 +45,16 @@ var filepathThree = path.join(testsubdir, filenameThree);
process.on('exit', function() {
- fs.unlinkSync(filepathOne);
- fs.unlinkSync(filepathTwoAbs);
- fs.unlinkSync(filepathThree);
- fs.rmdirSync(testsubdir);
assert.ok(watchSeenOne > 0);
assert.ok(watchSeenTwo > 0);
assert.ok(watchSeenThree > 0);
});
+// Clean up stale files (if any) from previous run.
+try { fs.unlinkSync(filepathOne); } catch (e) { }
+try { fs.unlinkSync(filepathTwoAbs); } catch (e) { }
+try { fs.unlinkSync(filepathThree); } catch (e) { }
+try { fs.rmdirSync(testsubdir); } catch (e) { }
fs.writeFileSync(filepathOne, 'hello');
@@ -141,3 +141,9 @@ setTimeout(function() {
var fd = fs.openSync(filepathThree, 'w');
fs.closeSync(fd);
}, 1000);
+
+// https://github.com/joyent/node/issues/2293 - non-persistent watcher should
+// not block the event loop
+fs.watch(__filename, {persistent: false}, function() {
+ assert(0);
+});
diff --git a/test/simple/test-http-parser-bad-ref.js b/test/simple/test-http-parser-bad-ref.js
new file mode 100644
index 0000000000..b8fd5b2917
--- /dev/null
+++ b/test/simple/test-http-parser-bad-ref.js
@@ -0,0 +1,72 @@
+// Run this program with valgrind or efence with --expose_gc to expose the
+// problem.
+
+// Flags: --expose_gc
+
+var assert = require('assert');
+var HTTPParser = process.binding('http_parser').HTTPParser;
+
+var headersComplete = 0;
+var messagesComplete = 0;
+
+function flushPool() {
+ new Buffer(Buffer.poolSize - 1);
+ gc();
+}
+
+function demoBug(part1, part2) {
+ var parser = new HTTPParser('REQUEST');
+
+ parser.headers = [];
+ parser.url = '';
+
+ parser.onHeaders = function(headers, url) {
+ parser.headers = parser.headers.concat(headers);
+ parser.url += url;
+ };
+
+ parser.onHeadersComplete = function(info) {
+ headersComplete++;
+ console.log("url", info.url);
+ };
+
+ parser.onBody = function(b, start, len) { };
+
+ parser.onMessageComplete = function() {
+ messagesComplete++;
+ };
+
+
+ // We use a function to eliminate references to the Buffer b
+ // We want b to be GCed. The parser will hold a bad reference to it.
+ (function() {
+ var b = Buffer(part1);
+ flushPool();
+
+ console.log("parse the first part of the message");
+ parser.execute(b, 0, b.length);
+ })();
+
+ flushPool();
+
+ (function() {
+ var b = Buffer(part2);
+
+ console.log("parse the second part of the message");
+ parser.execute(b, 0, b.length);
+ parser.finish();
+ })();
+}
+
+
+demoBug('POST /1', '/22 HTTP/1.1\r\n' +
+ 'Content-Type: text/plain\r\n' +
+ 'Content-Length: 4\r\n\r\n' +
+ 'pong');
+
+
+process.on('exit', function() {
+ assert.equal(1, headersComplete);
+ assert.equal(1, messagesComplete);
+ console.log("done!");
+});