herb 0.10.2-x86-linux-musl → 0.10.3-x86-linux-musl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/herb/3.2/herb.so +0 -0
- data/lib/herb/3.3/herb.so +0 -0
- data/lib/herb/3.4/herb.so +0 -0
- data/lib/herb/4.0/herb.so +0 -0
- data/lib/herb/cli.rb +6 -1
- data/lib/herb/engine/debug_visitor.rb +1 -1
- data/lib/herb/engine/parser_error_overlay.rb +2 -0
- data/lib/herb/project.rb +8 -5
- data/lib/herb/version.rb +1 -1
- data/src/analyze/action_view/tag_helpers.c +5 -0
- data/src/analyze/control_type.c +6 -8
- data/src/analyze/render_nodes.c +3 -0
- data/src/include/lexer/token.h +2 -0
- data/src/include/version.h +1 -1
- data/src/lexer/token.c +6 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9dc371ce28a6cfe6d92a4b900cb9624951744b17ce04d7e6a5db4570437b2a85
|
|
4
|
+
data.tar.gz: ef478f6167c9d141c28c2c6ba4a92442942e86699b0dede7b93a540964543e04
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 62131dbf43093b43cb8ade6b77e47aaec5b024a22983033bd56ff4d5d39f563f3289c0aff761a3e9057f286015cfddb725f95fffc5584746af7e59bb37974dfe
|
|
7
|
+
data.tar.gz: fd19b4898455016e19af67f6b362ded9759ad8208bc58a48e10d753831fb4884e881a3732bc078e1722df8ce279a189040a1ef2b502c7e7db1bcb97d03cfc077
|
data/lib/herb/3.2/herb.so
CHANGED
|
Binary file
|
data/lib/herb/3.3/herb.so
CHANGED
|
Binary file
|
data/lib/herb/3.4/herb.so
CHANGED
|
Binary file
|
data/lib/herb/4.0/herb.so
CHANGED
|
Binary file
|
data/lib/herb/cli.rb
CHANGED
|
@@ -8,7 +8,7 @@ require "optparse"
|
|
|
8
8
|
class Herb::CLI
|
|
9
9
|
include Herb::Colors
|
|
10
10
|
|
|
11
|
-
attr_accessor :json, :silent, :log_file, :no_timing, :local, :escape, :no_escape, :freeze, :debug, :tool, :strict, :analyze, :track_whitespace, :verbose, :isolate, :arena_stats, :leak_check, :action_view_helpers, :trim, :optimize
|
|
11
|
+
attr_accessor :json, :silent, :log_file, :no_timing, :local, :escape, :no_escape, :freeze, :debug, :tool, :strict, :analyze, :track_whitespace, :verbose, :isolate, :arena_stats, :leak_check, :action_view_helpers, :trim, :optimize, :file_timeout
|
|
12
12
|
|
|
13
13
|
def initialize(args)
|
|
14
14
|
@args = args
|
|
@@ -154,6 +154,7 @@ class Herb::CLI
|
|
|
154
154
|
project.silent = silent
|
|
155
155
|
project.verbose = verbose || ci?
|
|
156
156
|
project.isolate = isolate
|
|
157
|
+
project.file_timeout = file_timeout if file_timeout
|
|
157
158
|
project.validate_ruby = true
|
|
158
159
|
project.arena_stats = arena_stats
|
|
159
160
|
project.leak_check = leak_check
|
|
@@ -269,6 +270,10 @@ class Herb::CLI
|
|
|
269
270
|
self.isolate = true
|
|
270
271
|
end
|
|
271
272
|
|
|
273
|
+
parser.on("--timeout SECONDS", Float, "Per-file timeout for parse + compile (for analyze command) (default: #{Herb::Project::DEFAULT_FILE_TIMEOUT})") do |seconds|
|
|
274
|
+
self.file_timeout = seconds
|
|
275
|
+
end
|
|
276
|
+
|
|
272
277
|
parser.on("--log-file", "Enable log file generation") do
|
|
273
278
|
self.log_file = true
|
|
274
279
|
end
|
|
@@ -336,7 +336,7 @@ module Herb
|
|
|
336
336
|
end
|
|
337
337
|
|
|
338
338
|
def in_excluded_context?
|
|
339
|
-
excluded_tags = ["script", "style", "head", "textarea", "pre", "svg", "math"]
|
|
339
|
+
excluded_tags = ["script", "style", "head", "title", "textarea", "pre", "svg", "math"]
|
|
340
340
|
return true if excluded_tags.any? { |tag| @element_stack.include?(tag) }
|
|
341
341
|
|
|
342
342
|
if @erb_block_stack.any? { |node| javascript_tag?(node.content.value.strip) || include_debug_disable_comment?(node.content.value.strip) }
|
data/lib/herb/project.rb
CHANGED
|
@@ -12,7 +12,9 @@ module Herb
|
|
|
12
12
|
class Project
|
|
13
13
|
include Colors
|
|
14
14
|
|
|
15
|
-
attr_accessor :project_path, :output_file, :no_log_file, :no_timing, :silent, :verbose, :isolate, :validate_ruby, :file_paths, :arena_stats, :leak_check
|
|
15
|
+
attr_accessor :project_path, :output_file, :no_log_file, :no_timing, :silent, :verbose, :isolate, :validate_ruby, :file_paths, :arena_stats, :leak_check, :file_timeout
|
|
16
|
+
|
|
17
|
+
DEFAULT_FILE_TIMEOUT = 1 # seconds per file for parse + compile
|
|
16
18
|
|
|
17
19
|
# Known error types that indicate issues in the user's template, not bugs in the parser.
|
|
18
20
|
TEMPLATE_ERRORS = [
|
|
@@ -126,6 +128,7 @@ module Herb
|
|
|
126
128
|
|
|
127
129
|
date = Time.now.strftime("%Y-%m-%d_%H-%M-%S")
|
|
128
130
|
@output_file = output_file || "#{date}_erb_parsing_result_#{@project_path.basename}.log"
|
|
131
|
+
@file_timeout = DEFAULT_FILE_TIMEOUT
|
|
129
132
|
end
|
|
130
133
|
|
|
131
134
|
def configuration
|
|
@@ -354,7 +357,7 @@ module Herb
|
|
|
354
357
|
result[:leak_check] = capture_leak_check(file_content)
|
|
355
358
|
end
|
|
356
359
|
|
|
357
|
-
Timeout.timeout(
|
|
360
|
+
Timeout.timeout(file_timeout) do
|
|
358
361
|
parse_result = Herb.parse(file_content)
|
|
359
362
|
|
|
360
363
|
if parse_result.failed?
|
|
@@ -369,7 +372,7 @@ module Herb
|
|
|
369
372
|
result
|
|
370
373
|
rescue Timeout::Error
|
|
371
374
|
result.merge(status: :timeout, file_content: file_content,
|
|
372
|
-
log: "⏱️ Parsing #{file_path} timed out after
|
|
375
|
+
log: "⏱️ Parsing #{file_path} timed out after #{file_timeout} #{pluralize(file_timeout, "second")}")
|
|
373
376
|
rescue StandardError => e
|
|
374
377
|
file_content ||= begin
|
|
375
378
|
File.read(file_path)
|
|
@@ -388,7 +391,7 @@ module Herb
|
|
|
388
391
|
stdout_file = Tempfile.new("stdout")
|
|
389
392
|
stderr_file = Tempfile.new("stderr")
|
|
390
393
|
|
|
391
|
-
Timeout.timeout(
|
|
394
|
+
Timeout.timeout(file_timeout) do
|
|
392
395
|
pid = Process.fork do
|
|
393
396
|
$stdout.reopen(stdout_file.path, "w")
|
|
394
397
|
$stderr.reopen(stderr_file.path, "w")
|
|
@@ -431,7 +434,7 @@ module Herb
|
|
|
431
434
|
nil
|
|
432
435
|
end
|
|
433
436
|
|
|
434
|
-
{ file_path: file_path, status: :timeout, file_content: file_content, log: "⏱️ Parsing #{file_path} timed out after
|
|
437
|
+
{ file_path: file_path, status: :timeout, file_content: file_content, log: "⏱️ Parsing #{file_path} timed out after #{file_timeout} #{pluralize(file_timeout, "second")}" }
|
|
435
438
|
rescue StandardError => e
|
|
436
439
|
file_content ||= begin
|
|
437
440
|
File.read(file_path)
|
data/lib/herb/version.rb
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
#include "../../include/analyze/analyze.h"
|
|
6
6
|
#include "../../include/ast/ast_nodes.h"
|
|
7
7
|
#include "../../include/herb.h"
|
|
8
|
+
#include "../../include/lexer/token.h"
|
|
8
9
|
#include "../../include/lib/hb_allocator.h"
|
|
9
10
|
#include "../../include/lib/hb_array.h"
|
|
10
11
|
#include "../../include/lib/hb_buffer.h"
|
|
@@ -1426,6 +1427,8 @@ void transform_tag_helper_array(hb_array_T* array, analyze_ruby_context_T* conte
|
|
|
1426
1427
|
if (child->type == AST_ERB_BLOCK_NODE) {
|
|
1427
1428
|
AST_ERB_BLOCK_NODE_T* block_node = (AST_ERB_BLOCK_NODE_T*) child;
|
|
1428
1429
|
|
|
1430
|
+
if (token_is_escaped_erb_tag_opening(block_node->tag_opening)) { continue; }
|
|
1431
|
+
|
|
1429
1432
|
if (block_node->tag_opening && !hb_string_is_empty(block_node->tag_opening->value)) {
|
|
1430
1433
|
const char* opening_string = block_node->tag_opening->value.data;
|
|
1431
1434
|
if (opening_string && strstr(opening_string, "=") == NULL) { continue; }
|
|
@@ -1455,6 +1458,8 @@ void transform_tag_helper_array(hb_array_T* array, analyze_ruby_context_T* conte
|
|
|
1455
1458
|
AST_ERB_CONTENT_NODE_T* erb_node = (AST_ERB_CONTENT_NODE_T*) child;
|
|
1456
1459
|
token_T* tag_opening = erb_node->tag_opening;
|
|
1457
1460
|
|
|
1461
|
+
if (token_is_escaped_erb_tag_opening(tag_opening)) { continue; }
|
|
1462
|
+
|
|
1458
1463
|
if (tag_opening && !hb_string_is_empty(tag_opening->value)) {
|
|
1459
1464
|
const char* opening_string = tag_opening->value.data;
|
|
1460
1465
|
|
data/src/analyze/control_type.c
CHANGED
|
@@ -110,11 +110,10 @@ static bool find_earliest_control_keyword_walker(const pm_node_t* node, void* da
|
|
|
110
110
|
if (call->block != NULL && call->block->type == PM_BLOCK_NODE) {
|
|
111
111
|
pm_block_node_t* block_node = (pm_block_node_t*) call->block;
|
|
112
112
|
|
|
113
|
-
bool
|
|
114
|
-
bool
|
|
115
|
-
bool has_valid_brace_closing = is_closing_brace(block_node->closing_loc);
|
|
113
|
+
bool has_opening = is_do_block(block_node->opening_loc) || is_brace_block(block_node->opening_loc);
|
|
114
|
+
bool is_unclosed = !has_valid_block_closing(block_node->opening_loc, block_node->closing_loc);
|
|
116
115
|
|
|
117
|
-
if (
|
|
116
|
+
if (has_opening && is_unclosed) {
|
|
118
117
|
current_type = CONTROL_TYPE_BLOCK;
|
|
119
118
|
keyword_offset = (uint32_t) (node->location.start - context->source_start);
|
|
120
119
|
}
|
|
@@ -125,11 +124,10 @@ static bool find_earliest_control_keyword_walker(const pm_node_t* node, void* da
|
|
|
125
124
|
case PM_LAMBDA_NODE: {
|
|
126
125
|
pm_lambda_node_t* lambda = (pm_lambda_node_t*) node;
|
|
127
126
|
|
|
128
|
-
bool
|
|
129
|
-
bool
|
|
130
|
-
bool has_valid_brace_closing = is_closing_brace(lambda->closing_loc);
|
|
127
|
+
bool has_opening = is_do_block(lambda->opening_loc) || is_brace_block(lambda->opening_loc);
|
|
128
|
+
bool is_unclosed = !has_valid_block_closing(lambda->opening_loc, lambda->closing_loc);
|
|
131
129
|
|
|
132
|
-
if (
|
|
130
|
+
if (has_opening && is_unclosed) {
|
|
133
131
|
current_type = CONTROL_TYPE_BLOCK;
|
|
134
132
|
keyword_offset = (uint32_t) (node->location.start - context->source_start);
|
|
135
133
|
}
|
data/src/analyze/render_nodes.c
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
#include "../include/analyze/helpers.h"
|
|
6
6
|
#include "../include/ast/ast_nodes.h"
|
|
7
7
|
#include "../include/errors.h"
|
|
8
|
+
#include "../include/lexer/token.h"
|
|
8
9
|
#include "../include/lib/hb_allocator.h"
|
|
9
10
|
#include "../include/lib/hb_array.h"
|
|
10
11
|
#include "../include/lib/hb_string.h"
|
|
@@ -811,6 +812,7 @@ static AST_ERB_RENDER_NODE_T* try_transform_content_node(
|
|
|
811
812
|
) {
|
|
812
813
|
if (!erb_node->analyzed_ruby || !erb_node->analyzed_ruby->valid || !erb_node->analyzed_ruby->parsed) { return NULL; }
|
|
813
814
|
if (is_erb_comment_tag(erb_node->tag_opening)) { return NULL; }
|
|
815
|
+
if (token_is_escaped_erb_tag_opening(erb_node->tag_opening)) { return NULL; }
|
|
814
816
|
|
|
815
817
|
pm_call_node_t* render_call = find_render_call(erb_node->analyzed_ruby->root, &erb_node->analyzed_ruby->parser);
|
|
816
818
|
if (!render_call) { return NULL; }
|
|
@@ -840,6 +842,7 @@ static AST_ERB_RENDER_NODE_T* try_transform_block_node(
|
|
|
840
842
|
analyze_ruby_context_T* context
|
|
841
843
|
) {
|
|
842
844
|
if (!block_node->content || hb_string_is_empty(block_node->content->value)) { return NULL; }
|
|
845
|
+
if (token_is_escaped_erb_tag_opening(block_node->tag_opening)) { return NULL; }
|
|
843
846
|
|
|
844
847
|
const char* ruby_source = block_node->content->value.data;
|
|
845
848
|
size_t ruby_length = block_node->content->value.length;
|
data/src/include/lexer/token.h
CHANGED
data/src/include/version.h
CHANGED
data/src/lexer/token.c
CHANGED
|
@@ -228,6 +228,12 @@ bool token_value_empty(const token_T* token) {
|
|
|
228
228
|
return token == NULL || hb_string_is_empty(token->value);
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
+
bool token_is_escaped_erb_tag_opening(const token_T* token) {
|
|
232
|
+
if (token_value_empty(token)) { return false; }
|
|
233
|
+
|
|
234
|
+
return hb_string_starts_with(token->value, hb_string("<%%"));
|
|
235
|
+
}
|
|
236
|
+
|
|
231
237
|
void token_free(token_T* token, hb_allocator_T* allocator) {
|
|
232
238
|
if (!token) { return; }
|
|
233
239
|
|