diff options
-rw-r--r-- | src/nvim/eval.c | 31 | ||||
-rw-r--r-- | src/nvim/globals.h | 8 | ||||
-rw-r--r-- | src/nvim/os/input.c | 4 | ||||
-rw-r--r-- | test/functional/job/job_spec.lua | 48 | ||||
-rw-r--r-- | third-party/cmake/BuildLuarocks.cmake | 1 | ||||
-rw-r--r-- | third-party/utfTerminalDetailed.lua | 27 |
6 files changed, 78 insertions, 41 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 90ab471818..a3ef24f295 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -472,7 +472,7 @@ typedef struct { #define JobEventFreer(x) KMEMPOOL_INIT(JobEventPool, JobEvent, JobEventFreer) static kmempool_t(JobEventPool) *job_event_pool = NULL; -static bool defer_job_callbacks = true; +static int disable_job_defer = 0; /* * Initialize the global and v: variables. @@ -5963,11 +5963,12 @@ static bool get_dict_callback(dict_T *d, char *key, ufunc_T **result) uint8_t *name = di->di_tv.vval.v_string; uint8_t *n = name; - ufunc_T *rv; + ufunc_T *rv = NULL; if (*n > '9' || *n < '0') { - n = trans_function_name(&n, false, TFN_INT|TFN_QUIET, NULL); - rv = find_func(n); - free(n); + if ((n = trans_function_name(&n, false, TFN_INT|TFN_QUIET, NULL))) { + rv = find_func(n); + free(n); + } } else { // dict function, name is already translated rv = find_func(n); @@ -10921,9 +10922,16 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv) list_T *args = argvars[0].vval.v_list; list_T *rv = list_alloc(); - // must temporarily disable job event deferring so the callbacks are - // processed while waiting. - defer_job_callbacks = false; + ui_busy_start(); + // disable breakchecks, which could result in job callbacks being executed + // at unexpected places + disable_breakcheck++; + // disable job event deferring so the callbacks are processed while waiting. + if (!disable_job_defer++) { + // process any pending job events in the deferred queue, but only do this if + // deferred is not disabled(at the top-level `jobwait()` call) + event_process(); + } // For each item in the input list append an integer to the output list. -3 // is used to represent an invalid job id, -2 is for a interrupted job and // -1 for jobs that were skipped or timed out. @@ -10996,8 +11004,9 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv) // job exits data->status_ptr = NULL; } - // restore defer flag - defer_job_callbacks = true; + disable_job_defer--; + disable_breakcheck--; + ui_busy_stop(); rv->lv_refcount++; rettv->v_type = VAR_LIST; @@ -20175,7 +20184,7 @@ static inline void push_job_event(Job *job, ufunc_T *callback, event_push((Event) { .handler = on_job_event, .data = event_data - }, defer_job_callbacks); + }, !disable_job_defer); } static void on_job_stdout(RStream *rstream, void *job, bool eof) diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 158125c878..9eb70d37df 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -898,6 +898,14 @@ EXTERN FILE *scriptout INIT(= NULL); /* stream to write script to */ /* volatile because it is used in signal handler catch_sigint(). */ EXTERN volatile int got_int INIT(= FALSE); /* set to TRUE when interrupt signal occurred */ +EXTERN int disable_breakcheck INIT(= 0); // > 0 if breakchecks should be + // ignored. FIXME(tarruda): Hacky + // way to run functions that would + // result in *_breakcheck calls + // while events that would normally + // be deferred are being processed + // immediately. Ref: + // neovim/neovim#2371 EXTERN int bangredo INIT(= FALSE); /* set to TRUE with ! command */ EXTERN int searchcmdlen; /* length of previous search cmd */ EXTERN int reg_do_extmatch INIT(= 0); /* Used when compiling regexp: diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c index a409a9ed13..8002d528ed 100644 --- a/src/nvim/os/input.c +++ b/src/nvim/os/input.c @@ -128,7 +128,9 @@ bool os_char_avail(void) // Check for CTRL-C typed by reading all available characters. void os_breakcheck(void) { - event_poll(0); + if (!disable_breakcheck && !got_int) { + event_poll(0); + } } /// Test whether a file descriptor refers to a terminal. diff --git a/test/functional/job/job_spec.lua b/test/functional/job/job_spec.lua index c517ae4c1b..8191b63a1c 100644 --- a/test/functional/job/job_spec.lua +++ b/test/functional/job/job_spec.lua @@ -249,6 +249,52 @@ describe('jobs', function() eq({'notification', 'wait', {{-2}}}, next_msg()) end) + it('can be called recursively', function() + source([[ + let g:opts = {} + let g:counter = 0 + function g:opts.on_stdout(id, msg) + if self.state == 0 + if self.counter < 10 + call Run() + endif + let self.state = 1 + call jobsend(a:id, "line1\n") + elseif self.state == 1 + let self.state = 2 + call jobsend(a:id, "line2\n") + elseif self.state == 2 + let self.state = 3 + call jobsend(a:id, "line3\n") + else + call rpcnotify(g:channel, 'w', printf('job %d closed', self.counter)) + call jobclose(a:id, 'stdin') + endif + endfunction + function g:opts.on_exit() + call rpcnotify(g:channel, 'w', printf('job %d exited', self.counter)) + endfunction + function Run() + let g:counter += 1 + let j = copy(g:opts) + let j.state = 0 + let j.counter = g:counter + call jobwait([ + \ jobstart([&sh, '-c', 'echo ready; cat -'], j), + \ ]) + endfunction + ]]) + execute('call Run()') + local r + for i = 10, 1, -1 do + r = next_msg() + eq('job '..i..' closed', r[3][1]) + r = next_msg() + eq('job '..i..' exited', r[3][1]) + end + eq(10, nvim('eval', 'g:counter')) + end) + describe('with timeout argument', function() it('will return -1 if the wait timed out', function() source([[ @@ -292,7 +338,7 @@ describe('jobs', function() data[i] = data[i]:gsub('\n', '\000') end rv = table.concat(data, '\n') - rv = rv:gsub('\r\n$', '') + rv = rv:gsub('\r\n$', ''):gsub('^\r\n', '') if rv ~= '' then break end diff --git a/third-party/cmake/BuildLuarocks.cmake b/third-party/cmake/BuildLuarocks.cmake index baa3425918..d02b1939b5 100644 --- a/third-party/cmake/BuildLuarocks.cmake +++ b/third-party/cmake/BuildLuarocks.cmake @@ -57,7 +57,6 @@ add_custom_target(stable-busted-deps add_custom_command(OUTPUT ${DEPS_BIN_DIR}/busted COMMAND ${DEPS_BIN_DIR}/luarocks ARGS build https://raw.githubusercontent.com/Olivine-Labs/busted/master/busted-scm-0.rockspec CC=${DEPS_C_COMPILER} LD=${DEPS_C_COMPILER} - COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/utfTerminalDetailed.lua ${DEPS_INSTALL_DIR}/share/lua/5.1/busted/outputHandlers DEPENDS stable-busted-deps) add_custom_target(busted diff --git a/third-party/utfTerminalDetailed.lua b/third-party/utfTerminalDetailed.lua deleted file mode 100644 index 5a52dfa958..0000000000 --- a/third-party/utfTerminalDetailed.lua +++ /dev/null @@ -1,27 +0,0 @@ --- busted output handler that immediately prints file and test names before --- tests are executed. It simplifies identifying which tests are --- hanging/crashing -if package.config:sub(1,1) == '\\' and not os.getenv("ANSICON") then - -- Disable colors on Windows. - colors = setmetatable({}, {__index = function() return function(s) return s end end}) -else - colors = require 'term.colors' -end - -return function(options, busted) - local handler = require 'busted.outputHandlers.utfTerminal'(options, busted) - - handler.fileStart = function(name) - io.write('\n' .. colors.cyan(name) .. ':') - end - - handler.testStart = function(element, parent, status, debug) - io.write('\n ' .. handler.getFullName(element) .. ' ... ') - io.flush() - end - - busted.subscribe({ 'file', 'start' }, handler.fileStart) - busted.subscribe({ 'test', 'start' }, handler.testStart) - - return handler -end |