From 046616ba587dd8c41110b17064ce371b5bf092d5 Mon Sep 17 00:00:00 2001 From: Rhys van der Waerden Date: Fri, 25 Aug 2017 17:07:21 +1000 Subject: [PATCH] Add timeout option Add an option to specify a timeout for the runner process. --- README.md | 1 + erb_transformer.rb | 17 +++++++++++++---- index.js | 17 +++++++++++------ 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 7548075..2365515 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,7 @@ Can be configured with [UseEntry#options](https://webpack.js.org/configuration/m | `dependenciesRoot` | `"app"` | The root of your Rails project, relative to webpack's working directory. | | `engine` | `"erb"` | ERB Template engine, `"erubi"`, `"erubis"` and `"erb"` are supported. | | `runner` | `"./bin/rails runner"` | Command to run Ruby scripts, relative to webpack's working directory. | +| `timeout` | `0` | Timeout for the runner task in seconds. `0` is no timeout. Set this if you want a hanging runner to error out the build. For example, if your webpack process is running in a subdirectory of your Rails project: diff --git a/erb_transformer.rb b/erb_transformer.rb index b4862ba..b75c491 100644 --- a/erb_transformer.rb +++ b/erb_transformer.rb @@ -1,5 +1,8 @@ -delimiter = ARGV[0] -engine = ARGV[1] +require 'timeout' + +delimiter, engine, timeout = ARGV +timeout = Float(timeout) + handler = case engine when 'erubi' require 'erubi' @@ -13,8 +16,14 @@ else raise "Unknown templating engine `#{engine}`" end +source = begin + Timeout.timeout(timeout) { STDIN.read } +rescue Timeout::Error + raise "rails-erb-loader took longer than the specified #{timeout} second timeout" +end + if engine == 'erubi' - puts "#{delimiter}#{eval(handler.new(STDIN.read).src)}#{delimiter}" + puts "#{delimiter}#{eval(handler.new(source).src)}#{delimiter}" else - puts "#{delimiter}#{handler.new(STDIN.read).result}#{delimiter}" + puts "#{delimiter}#{handler.new(source).result}#{delimiter}" end diff --git a/index.js b/index.js index 648ee70..1f96c05 100644 --- a/index.js +++ b/index.js @@ -16,6 +16,9 @@ var ioDelimiter = '_' + '_RAILS_ERB_LOADER_DELIMETER__' /* Match any block comments that start with the string `rails-erb-loader-*`. */ var configCommentRegex = /\/\*\s*rails-erb-loader-([a-z-]*)\s*([\s\S]*?)\s*\*\//g +/* Absolute path to the Ruby script that does the ERB transformation. */ +var runnerPath = path.join(__dirname, 'erb_transformer.rb') + /* Takes a path and attaches `.rb` if it has no extension nor trailing slash. */ function defaultFileExtension (dependency) { return /((\.\w*)|\/)$/.test(dependency) ? dependency : dependency + '.rb' @@ -65,15 +68,16 @@ function parseDependencies (source, root) { /* Launch Rails in a child process and run the `erb_transformer.rb` script to * output transformed source. */ -function transformSource (runner, engine, source, map, callback) { +function transformSource (runner, config, source, map, callback) { var child = execFile( runner.file, runner.arguments.concat( - path.join(__dirname, 'erb_transformer.rb'), + runnerPath, ioDelimiter, - engine + config.engine, + config.timeout ), - function (error, stdout) { + function (error, stdout, stderr) { // Output is delimited to filter out unwanted warnings or other output // that we don't want in our files. var sourceRegex = new RegExp(ioDelimiter + '([\\s\\S]+)' + ioDelimiter) @@ -140,7 +144,8 @@ module.exports = function railsErbLoader (source, map) { var config = defaults({}, getOptions(loader), { dependenciesRoot: 'app', runner: './bin/rails runner', - engine: 'erb' + engine: 'erb', + timeout: 0 }) // Dependencies are only useful in development, so don't bother searching the @@ -159,7 +164,7 @@ module.exports = function railsErbLoader (source, map) { if (error) { callback(error) } else { - transformSource(runner, config.engine, source, map, callback) + transformSource(runner, config, source, map, callback) } }) }