herb 0.11.0-aarch64-linux-gnu → 0.11.2-aarch64-linux-gnu

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.
Files changed (273) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +4 -2
  3. data/config.yml +9 -0
  4. data/ext/herb/extconf.rb +8 -31
  5. data/ext/herb/nodes.c +90 -73
  6. data/ext/herb/parser_options_helpers.c +26 -0
  7. data/lib/herb/3.2/herb.so +0 -0
  8. data/lib/herb/3.3/herb.so +0 -0
  9. data/lib/herb/3.4/herb.so +0 -0
  10. data/lib/herb/4.0/herb.so +0 -0
  11. data/lib/herb/analysis/partial_index.rb +1 -1
  12. data/lib/herb/analysis/partial_resolution.rb +27 -0
  13. data/lib/herb/ast/helpers.rb +1 -1
  14. data/lib/herb/ast/nodes.rb +32 -6
  15. data/lib/herb/bootstrap.rb +6 -2
  16. data/lib/herb/configuration.rb +11 -1
  17. data/lib/herb/dev/classifier.rb +1 -1
  18. data/lib/herb/dev/runner.rb +6 -1
  19. data/lib/herb/engine/compiler.rb +52 -19
  20. data/lib/herb/engine/slots/dynamics_compiler.rb +63 -14
  21. data/lib/herb/engine/slots/markers.rb +24 -0
  22. data/lib/herb/engine/slots/state_compiler.rb +1 -2
  23. data/lib/herb/engine/slots/subtree_compiler.rb +1 -1
  24. data/lib/herb/engine/slots/visitor.rb +71 -32
  25. data/lib/herb/engine/visitors/instrumentation_visitor.rb +18 -6
  26. data/lib/herb/engine.rb +0 -2
  27. data/lib/herb/parser_options.rb +6 -3
  28. data/lib/herb/project.rb +19 -8
  29. data/lib/herb/version.rb +1 -1
  30. data/lib/herb.rb +1 -1
  31. data/sig/herb/analysis/partial_resolution.rbs +8 -0
  32. data/sig/herb/ast/nodes.rbs +10 -4
  33. data/sig/herb/bootstrap.rbs +2 -0
  34. data/sig/herb/configuration.rbs +3 -0
  35. data/sig/herb/dev/runner.rbs +3 -0
  36. data/sig/herb/engine/compiler.rbs +14 -3
  37. data/sig/herb/engine/slots/dynamics_compiler.rbs +27 -7
  38. data/sig/herb/engine/slots/markers.rbs +14 -0
  39. data/sig/herb/engine/slots/visitor.rbs +31 -13
  40. data/sig/herb/engine/visitors/instrumentation_visitor.rbs +5 -1
  41. data/sig/herb/parser_options.rbs +6 -4
  42. data/sig/herb.rbs +2 -2
  43. data/sig/serialized_ast_nodes.rbs +1 -0
  44. data/src/analyze/action_view/attribute_extraction_helpers.c +40 -21
  45. data/src/analyze/action_view/generated_handlers.c +36 -36
  46. data/src/analyze/action_view/image_tag.c +7 -3
  47. data/src/analyze/action_view/javascript_include_tag.c +6 -3
  48. data/src/analyze/action_view/link_to.c +23 -23
  49. data/src/analyze/action_view/registry.c +7 -3
  50. data/src/analyze/action_view/tag_helper_node_builders.c +12 -16
  51. data/src/analyze/action_view/tag_helpers.c +215 -110
  52. data/src/analyze/action_view/turbo_frame_tag.c +5 -4
  53. data/src/analyze/analyze.c +41 -45
  54. data/src/analyze/analyze_helpers.c +240 -405
  55. data/src/analyze/analyzed_ruby.c +10 -7
  56. data/src/analyze/builders.c +1 -0
  57. data/src/analyze/control_type.c +46 -29
  58. data/src/analyze/herb_directives.c +16 -20
  59. data/src/analyze/iteration_nodes.c +69 -24
  60. data/src/analyze/parse_errors.c +32 -22
  61. data/src/analyze/postfix_conditionals.c +23 -13
  62. data/src/analyze/prism_annotate.c +56 -32
  63. data/src/analyze/render_nodes.c +51 -41
  64. data/src/analyze/strict_locals.c +14 -15
  65. data/src/analyze/ternary_conditionals.c +14 -10
  66. data/src/ast/ast_nodes.c +3 -1
  67. data/src/ast/ast_pretty_print.c +5 -1
  68. data/src/extract.c +204 -143
  69. data/src/herb.c +10 -8
  70. data/src/include/analyze/action_view/tag_helper_handler.h +1 -1
  71. data/src/include/analyze/action_view/tag_helper_node_builders.h +1 -0
  72. data/src/include/analyze/action_view/tag_helpers.h +1 -1
  73. data/src/include/analyze/analyze.h +3 -24
  74. data/src/include/analyze/analyzed_ruby.h +29 -2
  75. data/src/include/analyze/helpers.h +7 -27
  76. data/src/include/ast/ast_nodes.h +2 -1
  77. data/src/include/herb.h +3 -2
  78. data/src/include/lexer/lexer.h +1 -0
  79. data/src/include/parser/parser_options.h +5 -0
  80. data/src/include/prism/herb_prism_node.h +6 -1
  81. data/src/include/prism/prism_context.h +12 -12
  82. data/src/include/prism/prism_helpers.h +30 -0
  83. data/src/include/prism_version.h +11 -0
  84. data/src/include/version.h +1 -1
  85. data/src/lexer.c +32 -0
  86. data/src/parser/parser_helpers.c +1 -2
  87. data/src/parser.c +6 -7
  88. data/src/parser_options_defaults.c +1 -0
  89. data/src/prism/prism_helpers.c +167 -42
  90. data/src/prism/ruby_parser.c +20 -20
  91. data/templates/ext/herb/nodes.c.erb +5 -5
  92. data/templates/ext/herb/parser_options_helpers.c.erb +33 -0
  93. data/templates/java/nodes.c.erb +6 -6
  94. data/templates/java/parser_options_helpers.c.erb +41 -2
  95. data/templates/java/parser_options_helpers.h.erb +2 -1
  96. data/templates/javascript/packages/core/src/nodes.ts.erb +21 -1
  97. data/templates/javascript/packages/node/extension/nodes.cpp.erb +5 -5
  98. data/templates/javascript/packages/node/extension/parser_options_helpers.cpp.erb +34 -2
  99. data/templates/javascript/packages/node/extension/parser_options_helpers.h.erb +1 -1
  100. data/templates/lib/herb/parser_options.rb.erb +1 -1
  101. data/templates/rust/src/ast/nodes.rs.erb +1 -4
  102. data/templates/rust/src/prism/generated_deserialize.rs.erb +90 -44
  103. data/templates/rust/src/prism/generated_prettyprint.rs.erb +18 -27
  104. data/templates/src/analyze/action_view/generated_handlers.c.erb +23 -22
  105. data/templates/src/include/parser/parser_options.h.erb +10 -0
  106. data/templates/src/include/prism_version.h.erb +17 -0
  107. data/templates/src/parser_options_defaults.c.erb +1 -1
  108. data/templates/template.rb +17 -2
  109. data/templates/wasm/nodes.cpp.erb +8 -18
  110. data/templates/wasm/parser_options_helpers.cpp.erb +24 -0
  111. data/vendor/prism/Rakefile +76 -7
  112. data/vendor/prism/config.yml +174 -161
  113. data/vendor/prism/include/prism/arena.h +45 -0
  114. data/vendor/prism/include/prism/arena.hpp +42 -0
  115. data/vendor/prism/include/prism/ast.h +2738 -611
  116. data/vendor/prism/include/prism/ast.hpp +641 -0
  117. data/vendor/prism/include/prism/buffer.h +60 -0
  118. data/vendor/prism/include/prism/buffer.hpp +55 -0
  119. data/vendor/prism/include/prism/comments.h +72 -0
  120. data/vendor/prism/include/prism/compiler/accel.h +26 -0
  121. data/vendor/prism/include/prism/compiler/align.h +36 -0
  122. data/vendor/prism/include/prism/compiler/assume.h +25 -0
  123. data/vendor/prism/include/prism/compiler/branch.h +26 -0
  124. data/vendor/prism/include/prism/compiler/bswap.h +46 -0
  125. data/vendor/prism/include/prism/compiler/cplusplus.hpp +16 -0
  126. data/vendor/prism/include/prism/compiler/endianness.h +34 -0
  127. data/vendor/prism/include/prism/compiler/exceptions.hpp +17 -0
  128. data/vendor/prism/include/prism/compiler/exported.h +24 -0
  129. data/vendor/prism/include/prism/compiler/fallthrough.h +22 -0
  130. data/vendor/prism/include/prism/compiler/filesystem.h +32 -0
  131. data/vendor/prism/include/prism/compiler/flex_array.h +19 -0
  132. data/vendor/prism/include/prism/compiler/force_inline.h +21 -0
  133. data/vendor/prism/include/prism/compiler/format.h +27 -0
  134. data/vendor/prism/include/prism/compiler/inline.h +17 -0
  135. data/vendor/prism/include/prism/compiler/lifetimebound.hpp +25 -0
  136. data/vendor/prism/include/prism/compiler/nodiscard.h +22 -0
  137. data/vendor/prism/include/prism/compiler/nonnull.h +18 -0
  138. data/vendor/prism/include/prism/compiler/unused.h +18 -0
  139. data/vendor/prism/include/prism/constant_pool.h +106 -0
  140. data/vendor/prism/include/prism/diagnostic.h +55 -402
  141. data/vendor/prism/include/prism/errors_format.h +61 -0
  142. data/vendor/prism/include/prism/excludes.h +29 -0
  143. data/vendor/prism/include/prism/integer.h +41 -0
  144. data/vendor/prism/include/prism/internal/allocator.h +68 -0
  145. data/vendor/prism/include/prism/internal/allocator_debug.h +88 -0
  146. data/vendor/prism/include/prism/internal/arena.h +108 -0
  147. data/vendor/prism/include/prism/internal/bit.h +42 -0
  148. data/vendor/prism/include/prism/internal/buffer.h +94 -0
  149. data/vendor/prism/include/prism/internal/char.h +145 -0
  150. data/vendor/prism/include/prism/internal/comments.h +54 -0
  151. data/vendor/prism/include/prism/internal/constant_pool.h +152 -0
  152. data/vendor/prism/include/prism/internal/diagnostic.h +389 -0
  153. data/vendor/prism/include/prism/{encoding.h → internal/encoding.h} +27 -68
  154. data/vendor/prism/include/prism/internal/integer.h +68 -0
  155. data/vendor/prism/include/prism/internal/isinf.h +16 -0
  156. data/vendor/prism/include/prism/internal/line_offset_list.h +34 -0
  157. data/vendor/prism/include/prism/{util/pm_list.h → internal/list.h} +11 -52
  158. data/vendor/prism/include/prism/internal/magic_comments.h +23 -0
  159. data/vendor/prism/include/prism/internal/memchr.h +15 -0
  160. data/vendor/prism/include/prism/internal/node.h +42 -0
  161. data/vendor/prism/include/prism/internal/options.h +232 -0
  162. data/vendor/prism/include/prism/internal/parser.h +1015 -0
  163. data/vendor/prism/include/prism/internal/regexp.h +26 -0
  164. data/vendor/prism/include/prism/internal/serialize.h +39 -0
  165. data/vendor/prism/include/prism/internal/source.h +72 -0
  166. data/vendor/prism/include/prism/internal/static_literals.h +60 -0
  167. data/vendor/prism/include/prism/internal/stringy.h +30 -0
  168. data/vendor/prism/include/prism/{util/pm_strncasecmp.h → internal/strncasecmp.h} +3 -17
  169. data/vendor/prism/include/prism/{util/pm_strpbrk.h → internal/strpbrk.h} +7 -20
  170. data/vendor/prism/include/prism/internal/tokens.h +11 -0
  171. data/vendor/prism/include/prism/internal/xxh3.h +16 -0
  172. data/vendor/prism/include/prism/json.h +40 -0
  173. data/vendor/prism/include/prism/line_offset_list.h +69 -0
  174. data/vendor/prism/include/prism/magic_comments.h +53 -0
  175. data/vendor/prism/include/prism/node.h +59 -49
  176. data/vendor/prism/include/prism/node.hpp +272 -0
  177. data/vendor/prism/include/prism/node_type.hpp +38 -0
  178. data/vendor/prism/include/prism/options.h +154 -279
  179. data/vendor/prism/include/prism/options.hpp +43 -0
  180. data/vendor/prism/include/prism/parser.h +367 -870
  181. data/vendor/prism/include/prism/parser.hpp +274 -0
  182. data/vendor/prism/include/prism/prettyprint.h +14 -9
  183. data/vendor/prism/include/prism/serialize.h +123 -0
  184. data/vendor/prism/include/prism/source.h +163 -0
  185. data/vendor/prism/include/prism/stream.h +36 -0
  186. data/vendor/prism/include/prism/string_query.h +82 -0
  187. data/vendor/prism/include/prism/stringy.h +61 -0
  188. data/vendor/prism/include/prism/stringy.hpp +31 -0
  189. data/vendor/prism/include/prism/version.h +20 -3
  190. data/vendor/prism/include/prism.h +35 -320
  191. data/vendor/prism/include/prism.hpp +24 -0
  192. data/vendor/prism/src/arena.c +122 -0
  193. data/vendor/prism/src/{util/pm_buffer.c → buffer.c} +53 -21
  194. data/vendor/prism/src/{util/pm_char.c → char.c} +28 -57
  195. data/vendor/prism/src/comments.c +455 -0
  196. data/vendor/prism/src/constant_pool.c +406 -0
  197. data/vendor/prism/src/diagnostic.c +120 -68
  198. data/vendor/prism/src/encoding.c +8 -3
  199. data/vendor/prism/src/errors_format.c +519 -0
  200. data/vendor/prism/src/{util/pm_integer.c → integer.c} +38 -22
  201. data/vendor/prism/src/json.c +5733 -0
  202. data/vendor/prism/src/line_offset_list.c +100 -0
  203. data/vendor/prism/src/list.c +24 -0
  204. data/vendor/prism/src/{util/pm_memchr.c → memchr.c} +8 -6
  205. data/vendor/prism/src/node.c +3465 -7787
  206. data/vendor/prism/src/options.c +161 -54
  207. data/vendor/prism/src/parser.c +371 -0
  208. data/vendor/prism/src/prettyprint.c +421 -354
  209. data/vendor/prism/src/prism.c +8522 -7280
  210. data/vendor/prism/src/regexp.c +960 -45
  211. data/vendor/prism/src/serialize.c +2434 -2048
  212. data/vendor/prism/src/source.c +524 -0
  213. data/vendor/prism/src/static_literals.c +303 -360
  214. data/vendor/prism/src/string_query.c +180 -0
  215. data/vendor/prism/src/stringy.c +61 -0
  216. data/vendor/prism/src/{util/pm_strncasecmp.c → strncasecmp.c} +5 -4
  217. data/vendor/prism/src/strpbrk.c +447 -0
  218. data/vendor/prism/src/{token_type.c → tokens.c} +39 -18
  219. data/vendor/prism/src/xxh3.c +292 -0
  220. data/vendor/prism/templates/ext/prism/api_node.c.erb +58 -44
  221. data/vendor/prism/templates/include/prism/ast.h.erb +67 -17
  222. data/vendor/prism/templates/include/prism/ast.hpp.erb +31 -0
  223. data/vendor/prism/templates/include/prism/internal/diagnostic.h.erb +60 -0
  224. data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/AbstractNodeVisitor.java.erb +1 -1
  225. data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/Loader.java.erb +232 -133
  226. data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/Nodes.java.erb +62 -23
  227. data/vendor/prism/templates/javascript/src/deserialize.js.erb +153 -146
  228. data/vendor/prism/templates/javascript/src/nodes.js.erb +4 -9
  229. data/vendor/prism/templates/lib/prism/compiler.rb.erb +14 -5
  230. data/vendor/prism/templates/lib/prism/dispatcher.rb.erb +20 -12
  231. data/vendor/prism/templates/lib/prism/dot_visitor.rb.erb +37 -11
  232. data/vendor/prism/templates/lib/prism/dsl.rb.erb +43 -4
  233. data/vendor/prism/templates/lib/prism/inspect_visitor.rb.erb +26 -10
  234. data/vendor/prism/templates/lib/prism/mutation_compiler.rb.erb +5 -2
  235. data/vendor/prism/templates/lib/prism/node.rb.erb +283 -105
  236. data/vendor/prism/templates/lib/prism/reflection.rb.erb +11 -2
  237. data/vendor/prism/templates/lib/prism/serialize.rb.erb +291 -134
  238. data/vendor/prism/templates/lib/prism/visitor.rb.erb +18 -0
  239. data/vendor/prism/templates/src/diagnostic.c.erb +114 -63
  240. data/vendor/prism/templates/src/json.c.erb +130 -0
  241. data/vendor/prism/templates/src/node.c.erb +79 -236
  242. data/vendor/prism/templates/src/prettyprint.c.erb +24 -13
  243. data/vendor/prism/templates/src/serialize.c.erb +369 -183
  244. data/vendor/prism/templates/src/{token_type.c.erb → tokens.c.erb} +22 -11
  245. data/vendor/prism/templates/template.rb +193 -91
  246. metadata +100 -42
  247. data/vendor/prism/include/prism/defines.h +0 -260
  248. data/vendor/prism/include/prism/pack.h +0 -163
  249. data/vendor/prism/include/prism/regexp.h +0 -43
  250. data/vendor/prism/include/prism/static_literals.h +0 -121
  251. data/vendor/prism/include/prism/util/pm_buffer.h +0 -236
  252. data/vendor/prism/include/prism/util/pm_char.h +0 -204
  253. data/vendor/prism/include/prism/util/pm_constant_pool.h +0 -218
  254. data/vendor/prism/include/prism/util/pm_integer.h +0 -130
  255. data/vendor/prism/include/prism/util/pm_memchr.h +0 -29
  256. data/vendor/prism/include/prism/util/pm_newline_list.h +0 -113
  257. data/vendor/prism/include/prism/util/pm_string.h +0 -200
  258. data/vendor/prism/src/pack.c +0 -509
  259. data/vendor/prism/src/util/pm_constant_pool.c +0 -342
  260. data/vendor/prism/src/util/pm_list.c +0 -49
  261. data/vendor/prism/src/util/pm_newline_list.c +0 -125
  262. data/vendor/prism/src/util/pm_string.c +0 -381
  263. data/vendor/prism/src/util/pm_strpbrk.c +0 -206
  264. data/vendor/prism/templates/include/prism/diagnostic.h.erb +0 -130
  265. data/vendor/prism/templates/rbi/prism/dsl.rbi.erb +0 -68
  266. data/vendor/prism/templates/rbi/prism/node.rbi.erb +0 -167
  267. data/vendor/prism/templates/rbi/prism/visitor.rbi.erb +0 -18
  268. data/vendor/prism/templates/sig/prism/_private/dot_visitor.rbs.erb +0 -45
  269. data/vendor/prism/templates/sig/prism/dsl.rbs.erb +0 -31
  270. data/vendor/prism/templates/sig/prism/mutation_compiler.rbs.erb +0 -7
  271. data/vendor/prism/templates/sig/prism/node.rbs.erb +0 -136
  272. data/vendor/prism/templates/sig/prism/visitor.rbs.erb +0 -17
  273. data/vendor/prism/templates/sig/prism.rbs.erb +0 -92
@@ -18,6 +18,8 @@
18
18
  #include "../../include/util/util.h"
19
19
  #include "../../include/visitor.h"
20
20
 
21
+ #include "../../include/prism/prism_helpers.h"
22
+
21
23
  #include <prism.h>
22
24
  #include <stdbool.h>
23
25
  #include <stdlib.h>
@@ -42,7 +44,9 @@ extern char* wrap_in_stylesheet_path(const char*, size_t, const char*, hb_alloca
42
44
  extern bool stylesheet_link_tag_source_is_url(const char*, size_t);
43
45
 
44
46
  typedef struct {
45
- pm_parser_t parser;
47
+ pm_arena_t* arena;
48
+ pm_parser_t* parser;
49
+ pm_options_t* options;
46
50
  pm_node_t* root;
47
51
  const uint8_t* prism_source;
48
52
  char* content_string;
@@ -60,46 +64,42 @@ typedef struct {
60
64
  } local_read_search_T;
61
65
 
62
66
  static void append_local_read_constant(local_read_search_T* search, pm_constant_id_t constant_id) {
63
- pm_constant_t* constant = pm_constant_pool_id_to_constant(&search->scope->parser.constant_pool, constant_id);
67
+ const pm_constant_t* constant = pm_parser_constant(search->scope->parser, constant_id);
68
+
69
+ if (!constant || pm_constant_length(constant) == 0) { return; }
64
70
 
65
- if (!constant || constant->length == 0) { return; }
71
+ size_t length = pm_constant_length(constant);
66
72
 
67
73
  for (size_t index = 0; index < hb_array_size(search->constants); index++) {
68
- pm_constant_t* existing = hb_array_get(search->constants, index);
74
+ const pm_constant_t* existing = hb_array_get(search->constants, index);
69
75
 
70
- if (existing && existing->length == constant->length
71
- && memcmp(existing->start, constant->start, constant->length) == 0) {
76
+ if (existing && pm_constant_length(existing) == length
77
+ && memcmp(pm_constant_start(existing), pm_constant_start(constant), length) == 0) {
72
78
  return;
73
79
  }
74
80
  }
75
81
 
76
- hb_array_append(search->constants, constant);
82
+ hb_array_append(search->constants, (void*) constant);
77
83
  }
78
84
 
79
- static bool search_local_variable_reads(const pm_node_t* node, void* data) {
85
+ static pm_visit_result_t search_local_variable_reads(const pm_node_t* node, void* data) {
80
86
  local_read_search_T* search = (local_read_search_T*) data;
81
- const uint8_t* base = (const uint8_t*) search->scope->buffer.value;
82
87
 
83
- size_t start = (size_t) (node->location.start - base);
84
- size_t end = (size_t) (node->location.end - base);
88
+ size_t start = node->location.start;
89
+ size_t end = herb_prism_location_end(node->location);
85
90
 
86
- if (end <= search->from || start >= search->to) { return false; }
91
+ if (end <= search->from || start >= search->to) { return PM_VISIT_SKIP; }
87
92
 
88
93
  if (PM_NODE_TYPE(node) == PM_LOCAL_VARIABLE_READ_NODE && start >= search->from && end <= search->to) {
89
94
  append_local_read_constant(search, ((pm_local_variable_read_node_t*) node)->name);
90
95
  }
91
96
 
92
- return true;
97
+ return PM_VISIT_DESCEND;
93
98
  }
94
99
 
95
- static bool build_scope_options_from_context(
96
- analyze_ruby_context_T* context,
97
- pm_options_t* options,
98
- size_t from,
99
- size_t to
100
- ) {
101
- if (!context || !context->tag_helper_scope || !context->tag_helper_scope->root) { return false; }
102
- if (to <= from) { return false; }
100
+ static pm_options_t* build_scope_options_from_context(analyze_ruby_context_T* context, size_t from, size_t to) {
101
+ if (!context || !context->tag_helper_scope || !context->tag_helper_scope->root) { return NULL; }
102
+ if (to <= from) { return NULL; }
103
103
 
104
104
  local_read_search_T search = { .scope = context->tag_helper_scope,
105
105
  .constants = hb_array_init(4, context->allocator),
@@ -109,27 +109,78 @@ static bool build_scope_options_from_context(
109
109
  pm_visit_node(context->tag_helper_scope->root, search_local_variable_reads, &search);
110
110
 
111
111
  size_t locals_count = hb_array_size(search.constants);
112
- bool built = false;
112
+ pm_options_t* options = NULL;
113
+
114
+ if (locals_count > 0) {
115
+ options = pm_options_new();
116
+ herb_prism_options_set_ruby_version(options, context->options);
113
117
 
114
- if (locals_count > 0 && pm_options_scopes_init(options, 1)) {
115
- pm_options_scope_t* scope = &options->scopes[0];
118
+ if (pm_options_scopes_init(options, 1)) {
119
+ pm_options_scope_t* scope = pm_options_scope_mut(options, 0);
120
+ pm_options_scope_init(scope, locals_count);
116
121
 
117
- if (pm_options_scope_init(scope, locals_count)) {
118
122
  for (size_t index = 0; index < locals_count; index++) {
119
- pm_constant_t* constant = hb_array_get(search.constants, index);
123
+ const pm_constant_t* constant = hb_array_get(search.constants, index);
120
124
 
121
- pm_string_constant_init(&scope->locals[index], (const char*) constant->start, constant->length);
125
+ pm_string_init(
126
+ pm_options_scope_local_mut(scope, index),
127
+ pm_constant_start(constant),
128
+ pm_constant_length(constant)
129
+ );
122
130
  }
123
-
124
- built = true;
125
131
  } else {
126
132
  pm_options_free(options);
133
+ options = NULL;
127
134
  }
128
135
  }
129
136
 
130
137
  hb_array_free(&search.constants);
131
138
 
132
- return built;
139
+ return options;
140
+ }
141
+
142
+ static bool symbol_node_equals(pm_node_t* node, const char* name) {
143
+ if (!node || node->type != PM_SYMBOL_NODE) { return false; }
144
+
145
+ pm_symbol_node_t* symbol = (pm_symbol_node_t*) node;
146
+ size_t length = pm_string_length(&symbol->unescaped);
147
+
148
+ return length == strlen(name) && strncmp((const char*) pm_string_source(&symbol->unescaped), name, length) == 0;
149
+ }
150
+
151
+ static bool asset_tag_resolves_at_render_time(pm_call_node_t* call_node, const char* helper_name) {
152
+ bool is_stylesheet_link_tag = string_equals(helper_name, "stylesheet_link_tag");
153
+
154
+ if (!is_stylesheet_link_tag && !string_equals(helper_name, "javascript_include_tag")) { return false; }
155
+ if (!call_node || !call_node->arguments) { return false; }
156
+
157
+ pm_node_list_t* arguments = &call_node->arguments->arguments;
158
+
159
+ for (size_t i = 0; i < arguments->size; i++) {
160
+ pm_node_t* argument = arguments->nodes[i];
161
+
162
+ if (argument->type == PM_SPLAT_NODE || argument->type == PM_ARRAY_NODE) { return true; }
163
+
164
+ if (is_stylesheet_link_tag && i == 0
165
+ && (symbol_node_equals(argument, "all") || symbol_node_equals(argument, "app"))) {
166
+ return true;
167
+ }
168
+
169
+ if (argument->type != PM_KEYWORD_HASH_NODE) { continue; }
170
+
171
+ pm_keyword_hash_node_t* hash = (pm_keyword_hash_node_t*) argument;
172
+
173
+ for (size_t j = 0; j < hash->elements.size; j++) {
174
+ pm_node_t* element = hash->elements.nodes[j];
175
+ if (element->type != PM_ASSOC_NODE) { continue; }
176
+
177
+ pm_assoc_node_t* assoc = (pm_assoc_node_t*) element;
178
+
179
+ if (symbol_node_equals(assoc->key, "integrity") && assoc->value->type != PM_STRING_NODE) { return true; }
180
+ }
181
+ }
182
+
183
+ return false;
133
184
  }
134
185
 
135
186
  static tag_helper_parse_context_T* parse_tag_helper_content(
@@ -151,22 +202,27 @@ static tag_helper_parse_context_T* parse_tag_helper_content(
151
202
 
152
203
  size_t content_length = strlen(parse_context->content_string);
153
204
 
154
- pm_options_t options = { 0 };
155
- bool has_scope_options =
156
- build_scope_options_from_context(context, &options, erb_content_offset, erb_content_offset + content_length);
205
+ parse_context->options =
206
+ build_scope_options_from_context(context, erb_content_offset, erb_content_offset + content_length);
157
207
 
158
- pm_parser_init(
159
- &parse_context->parser,
160
- parse_context->prism_source,
161
- content_length,
162
- has_scope_options ? &options : NULL
163
- );
164
- parse_context->root = pm_parse(&parse_context->parser);
165
-
166
- if (has_scope_options) { pm_options_free(&options); }
208
+ parse_context->arena = pm_arena_new();
209
+ if (parse_context->options) {
210
+ parse_context->parser =
211
+ pm_parser_new(parse_context->arena, parse_context->prism_source, content_length, parse_context->options);
212
+ } else {
213
+ parse_context->parser = herb_prism_parser_new(
214
+ parse_context->arena,
215
+ parse_context->prism_source,
216
+ content_length,
217
+ context ? context->options : NULL
218
+ );
219
+ }
220
+ parse_context->root = pm_parse(parse_context->parser);
167
221
 
168
222
  if (!parse_context->root) {
169
- pm_parser_free(&parse_context->parser);
223
+ pm_parser_free(parse_context->parser);
224
+ pm_arena_free(parse_context->arena);
225
+ if (parse_context->options) { pm_options_free(parse_context->options); }
170
226
  hb_allocator_dealloc(allocator, parse_context->content_string);
171
227
  hb_allocator_dealloc(allocator, parse_context);
172
228
  return NULL;
@@ -176,15 +232,17 @@ static tag_helper_parse_context_T* parse_tag_helper_content(
176
232
 
177
233
  tag_helper_search_data_T search = { .tag_helper_node = NULL,
178
234
  .source = parse_context->prism_source,
179
- .parser = &parse_context->parser,
235
+ .parser = parse_context->parser,
180
236
  .info = parse_context->info,
181
237
  .found = false };
182
238
  pm_visit_node(parse_context->root, search_tag_helper_node, &search);
183
239
 
184
- if (!search.found) {
240
+ if (!search.found
241
+ || asset_tag_resolves_at_render_time(parse_context->info->call_node, search.matched_handler->name)) {
185
242
  tag_helper_info_free(&parse_context->info);
186
- pm_node_destroy(&parse_context->parser, parse_context->root);
187
- pm_parser_free(&parse_context->parser);
243
+ pm_parser_free(parse_context->parser);
244
+ pm_arena_free(parse_context->arena);
245
+ if (parse_context->options) { pm_options_free(parse_context->options); }
188
246
  hb_allocator_dealloc(allocator, parse_context->content_string);
189
247
  hb_allocator_dealloc(allocator, parse_context);
190
248
  return NULL;
@@ -200,8 +258,9 @@ static void free_tag_helper_parse_context(tag_helper_parse_context_T* parse_cont
200
258
  hb_allocator_T* allocator = parse_context->info ? parse_context->info->allocator : NULL;
201
259
 
202
260
  tag_helper_info_free(&parse_context->info);
203
- pm_node_destroy(&parse_context->parser, parse_context->root);
204
- pm_parser_free(&parse_context->parser);
261
+ pm_parser_free(parse_context->parser);
262
+ pm_arena_free(parse_context->arena);
263
+ if (parse_context->options) { pm_options_free(parse_context->options); }
205
264
 
206
265
  if (allocator) {
207
266
  hb_allocator_dealloc(allocator, parse_context->content_string);
@@ -209,7 +268,7 @@ static void free_tag_helper_parse_context(tag_helper_parse_context_T* parse_cont
209
268
  }
210
269
  }
211
270
 
212
- bool search_tag_helper_node(const pm_node_t* node, void* data) {
271
+ pm_visit_result_t search_tag_helper_node(const pm_node_t* node, void* data) {
213
272
  tag_helper_search_data_T* search_data = (tag_helper_search_data_T*) data;
214
273
 
215
274
  if (node->type == PM_CALL_NODE) {
@@ -235,16 +294,16 @@ bool search_tag_helper_node(const pm_node_t* node, void* data) {
235
294
  search_data->info->has_block = handlers[i]->supports_block();
236
295
  }
237
296
 
238
- return false;
297
+ return PM_VISIT_SKIP;
239
298
  }
240
299
  }
241
300
 
242
- return false;
301
+ return PM_VISIT_SKIP;
243
302
  }
244
303
 
245
304
  pm_visit_child_nodes(node, search_tag_helper_node, search_data);
246
305
 
247
- return search_data->found;
306
+ return search_data->found ? PM_VISIT_DESCEND : PM_VISIT_SKIP;
248
307
  }
249
308
 
250
309
  position_T byte_offset_to_position(const char* source, size_t offset) {
@@ -252,13 +311,17 @@ position_T byte_offset_to_position(const char* source, size_t offset) {
252
311
 
253
312
  if (!source) { return position; }
254
313
 
255
- for (size_t i = 0; i < offset && source[i] != '\0'; i++) {
256
- if (source[i] == '\n') {
257
- position.line++;
258
- position.column = 1;
259
- } else if (!utf8_is_valid_continuation_byte((unsigned char) source[i])) {
260
- position.column++;
261
- }
314
+ const char* cursor = source;
315
+ const char* end = source + strnlen(source, offset);
316
+ const char* newline = NULL;
317
+
318
+ while ((newline = memchr(cursor, '\n', (size_t) (end - cursor))) != NULL) {
319
+ position.line++;
320
+ cursor = newline + 1;
321
+ }
322
+
323
+ for (; cursor < end; cursor++) {
324
+ if (!utf8_is_valid_continuation_byte((unsigned char) *cursor)) { position.column++; }
262
325
  }
263
326
 
264
327
  return position;
@@ -272,38 +335,47 @@ position_T prism_location_to_position_with_offset(
272
335
  ) {
273
336
  position_T default_position = { .line = 1, .column = 1 };
274
337
 
275
- if (!pm_location || !pm_location->start || !original_source || !erb_content_source) { return default_position; }
338
+ if (!pm_location || !herb_prism_location_assigned(*pm_location) || !original_source || !erb_content_source) {
339
+ return default_position;
340
+ }
276
341
 
277
- size_t offset_in_erb = (size_t) (pm_location->start - erb_content_source);
342
+ size_t offset_in_erb = pm_location->start;
278
343
  size_t total_offset = erb_content_offset + offset_in_erb;
279
344
 
280
- size_t source_length = strlen(original_source);
281
- if (total_offset > source_length) { return byte_offset_to_position(original_source, erb_content_offset); }
345
+ if (strnlen(original_source, total_offset) < total_offset) {
346
+ return byte_offset_to_position(original_source, erb_content_offset);
347
+ }
282
348
 
283
349
  return byte_offset_to_position(original_source, total_offset);
284
350
  }
285
351
 
286
352
  size_t calculate_byte_offset_from_position(const char* source, position_T position) {
287
353
  if (!source) { return 0; }
354
+ if (position.line == 0) { return strlen(source); }
355
+
356
+ const char* line_start = source;
357
+
358
+ for (uint32_t line = 1; line < position.line; line++) {
359
+ const char* newline = strchr(line_start, '\n');
360
+
361
+ if (!newline) { return (size_t) (line_start - source) + strlen(line_start); }
362
+
363
+ line_start = newline + 1;
364
+ }
288
365
 
289
- size_t offset = 0;
290
- uint32_t line = 1;
366
+ size_t offset = (size_t) (line_start - source);
291
367
  uint32_t column = 1;
292
368
 
293
369
  while (source[offset] != '\0') {
294
- if (line == position.line && column == position.column) { return offset; }
370
+ if (column == position.column) { return offset; }
371
+ if (source[offset] == '\n') { break; }
295
372
 
296
- if (source[offset] == '\n') {
297
- line++;
298
- column = 1;
299
- } else if (!utf8_is_valid_continuation_byte((unsigned char) source[offset])) {
300
- column++;
301
- }
373
+ if (!utf8_is_valid_continuation_byte((unsigned char) source[offset])) { column++; }
302
374
 
303
375
  offset++;
304
376
  }
305
377
 
306
- return offset;
378
+ return offset + strlen(source + offset);
307
379
  }
308
380
 
309
381
  static void prism_node_location_to_positions(
@@ -319,7 +391,7 @@ static void prism_node_location_to_positions(
319
391
  parse_context->prism_source
320
392
  );
321
393
 
322
- pm_location_t end_location = { .start = location->end, .end = location->end };
394
+ pm_location_t end_location = { .start = herb_prism_location_end(*location), .length = 0 };
323
395
  *out_end = prism_location_to_position_with_offset(
324
396
  &end_location,
325
397
  parse_context->original_source,
@@ -338,7 +410,7 @@ static void calculate_tag_name_positions(
338
410
  *out_start = default_start;
339
411
  *out_end = default_end;
340
412
 
341
- if (parse_context->info->call_node && parse_context->info->call_node->message_loc.start) {
413
+ if (parse_context->info->call_node && herb_prism_location_assigned(parse_context->info->call_node->message_loc)) {
342
414
  prism_node_location_to_positions(&parse_context->info->call_node->message_loc, parse_context, out_start, out_end);
343
415
  }
344
416
  }
@@ -349,6 +421,7 @@ static const char* IMAGE_TAG_PATH_OPTIONS[] = { "skip_pipeline", NULL };
349
421
 
350
422
  static char* extract_path_options_from_keyword_hash(
351
423
  pm_call_node_t* call_node,
424
+ const uint8_t* source,
352
425
  const char** option_names,
353
426
  hb_allocator_T* allocator
354
427
  ) {
@@ -393,12 +466,18 @@ static char* extract_path_options_from_keyword_hash(
393
466
  if (!first) { hb_buffer_append(&buffer, ", "); }
394
467
  first = false;
395
468
 
396
- size_t key_source_length = assoc->key->location.end - assoc->key->location.start;
397
- hb_buffer_append_with_length(&buffer, (const char*) assoc->key->location.start, key_source_length);
469
+ hb_buffer_append_with_length(
470
+ &buffer,
471
+ (const char*) (source + assoc->key->location.start),
472
+ assoc->key->location.length
473
+ );
398
474
  hb_buffer_append(&buffer, " ");
399
475
 
400
- size_t value_source_length = assoc->value->location.end - assoc->value->location.start;
401
- hb_buffer_append_with_length(&buffer, (const char*) assoc->value->location.start, value_source_length);
476
+ hb_buffer_append_with_length(
477
+ &buffer,
478
+ (const char*) (source + assoc->value->location.start),
479
+ assoc->value->location.length
480
+ );
402
481
  }
403
482
 
404
483
  if (first) {
@@ -456,8 +535,11 @@ static hb_array_T* prepend_stylesheet_link_tag_attributes(
456
535
  size_t length = pm_string_length(&string_node->unescaped);
457
536
  source_value = hb_allocator_strndup(allocator, (const char*) pm_string_source(&string_node->unescaped), length);
458
537
  } else {
459
- size_t length = source_argument->location.end - source_argument->location.start;
460
- source_value = hb_allocator_strndup(allocator, (const char*) source_argument->location.start, length);
538
+ source_value = hb_allocator_strndup(
539
+ allocator,
540
+ (const char*) (parse_context->prism_source + source_argument->location.start),
541
+ source_argument->location.length
542
+ );
461
543
  }
462
544
 
463
545
  if (!source_value) { return attributes; }
@@ -467,7 +549,7 @@ static hb_array_T* prepend_stylesheet_link_tag_attributes(
467
549
 
468
550
  size_t source_length = strlen(source_value);
469
551
  bool is_url = stylesheet_link_tag_source_is_url(source_value, source_length);
470
- bool source_is_path_helper = is_route_helper_node(source_argument, &parse_context->parser);
552
+ bool source_is_path_helper = is_route_helper_node(source_argument, parse_context->parser);
471
553
 
472
554
  char* href_value = source_value;
473
555
 
@@ -547,6 +629,7 @@ static AST_NODE_T* transform_tag_helper_with_attributes(
547
629
  if (attributes && handler->name && strcmp(handler->name, "javascript_include_tag") == 0) {
548
630
  path_options = extract_path_options_from_keyword_hash(
549
631
  parse_context->info->call_node,
632
+ parse_context->prism_source,
550
633
  JAVASCRIPT_INCLUDE_TAG_PATH_OPTIONS,
551
634
  allocator
552
635
  );
@@ -560,6 +643,7 @@ static AST_NODE_T* transform_tag_helper_with_attributes(
560
643
  if (attributes && handler->name && strcmp(handler->name, "stylesheet_link_tag") == 0) {
561
644
  path_options = extract_path_options_from_keyword_hash(
562
645
  parse_context->info->call_node,
646
+ parse_context->prism_source,
563
647
  STYLESHEET_LINK_TAG_PATH_OPTIONS,
564
648
  allocator
565
649
  );
@@ -571,8 +655,12 @@ static AST_NODE_T* transform_tag_helper_with_attributes(
571
655
  }
572
656
 
573
657
  if (attributes && handler->name && strcmp(handler->name, "image_tag") == 0) {
574
- path_options =
575
- extract_path_options_from_keyword_hash(parse_context->info->call_node, IMAGE_TAG_PATH_OPTIONS, allocator);
658
+ path_options = extract_path_options_from_keyword_hash(
659
+ parse_context->info->call_node,
660
+ parse_context->prism_source,
661
+ IMAGE_TAG_PATH_OPTIONS,
662
+ allocator
663
+ );
576
664
  discard_attribute_by_name(attributes, "skip-pipeline", allocator);
577
665
 
578
666
  AST_NODE_T* size_node = remove_attribute_by_name(attributes, "size");
@@ -666,7 +754,7 @@ static AST_NODE_T* transform_tag_helper_with_attributes(
666
754
  bool content_is_ruby_expression = false;
667
755
 
668
756
  if (parse_context->info->call_node && handler->extract_content) {
669
- helper_content = handler->extract_content(parse_context->info->call_node, &parse_context->parser, allocator);
757
+ helper_content = handler->extract_content(parse_context->info->call_node, parse_context->parser, allocator);
670
758
 
671
759
  if (helper_content) {
672
760
  pm_call_node_t* call = parse_context->info->call_node;
@@ -695,8 +783,8 @@ static AST_NODE_T* transform_tag_helper_with_attributes(
695
783
  }
696
784
  }
697
785
 
698
- if (detect_turbo_frame_tag(parse_context->info->call_node, &parse_context->parser)) {
699
- char* id_value = extract_turbo_frame_tag_id(parse_context->info->call_node, &parse_context->parser, allocator);
786
+ if (detect_turbo_frame_tag(parse_context->info->call_node, parse_context->parser)) {
787
+ char* id_value = extract_turbo_frame_tag_id(parse_context->info->call_node, parse_context->parser, allocator);
700
788
 
701
789
  if (id_value) {
702
790
  if (!attributes) { attributes = hb_array_init(4, allocator); }
@@ -724,10 +812,10 @@ static AST_NODE_T* transform_tag_helper_with_attributes(
724
812
  }
725
813
  }
726
814
 
727
- if (detect_javascript_include_tag(parse_context->info->call_node, &parse_context->parser)
815
+ if (detect_javascript_include_tag(parse_context->info->call_node, parse_context->parser)
728
816
  && parse_context->info->call_node->arguments && parse_context->info->call_node->arguments->arguments.size >= 1) {
729
817
  char* source_value =
730
- extract_javascript_include_tag_src(parse_context->info->call_node, &parse_context->parser, allocator);
818
+ extract_javascript_include_tag_src(parse_context->info->call_node, parse_context->parser, allocator);
731
819
 
732
820
  if (source_value) {
733
821
  if (!attributes) { attributes = hb_array_init(4, allocator); }
@@ -765,9 +853,9 @@ static AST_NODE_T* transform_tag_helper_with_attributes(
765
853
  }
766
854
  }
767
855
 
768
- if (detect_image_tag(parse_context->info->call_node, &parse_context->parser)
856
+ if (detect_image_tag(parse_context->info->call_node, parse_context->parser)
769
857
  && parse_context->info->call_node->arguments && parse_context->info->call_node->arguments->arguments.size >= 1) {
770
- char* source_value = extract_image_tag_src(parse_context->info->call_node, &parse_context->parser, allocator);
858
+ char* source_value = extract_image_tag_src(parse_context->info->call_node, parse_context->parser, allocator);
771
859
 
772
860
  if (source_value) {
773
861
  if (!attributes) { attributes = hb_array_init(4, allocator); }
@@ -776,7 +864,7 @@ static AST_NODE_T* transform_tag_helper_with_attributes(
776
864
  position_T source_start, source_end;
777
865
  prism_node_location_to_positions(&first_argument->location, parse_context, &source_start, &source_end);
778
866
  bool source_is_string = (first_argument->type == PM_STRING_NODE);
779
- bool source_is_path_helper = is_route_helper_node(first_argument, &parse_context->parser);
867
+ bool source_is_path_helper = is_route_helper_node(first_argument, parse_context->parser);
780
868
 
781
869
  size_t source_length = strlen(source_value);
782
870
  bool is_url = image_tag_source_is_url(source_value, source_length);
@@ -809,7 +897,7 @@ static AST_NODE_T* transform_tag_helper_with_attributes(
809
897
  }
810
898
  }
811
899
 
812
- if (detect_stylesheet_link_tag(parse_context->info->call_node, &parse_context->parser)
900
+ if (detect_stylesheet_link_tag(parse_context->info->call_node, parse_context->parser)
813
901
  && parse_context->info->call_node->arguments && parse_context->info->call_node->arguments->arguments.size >= 1) {
814
902
  pm_node_t* first_argument = parse_context->info->call_node->arguments->arguments.nodes[0];
815
903
 
@@ -1000,8 +1088,11 @@ static AST_NODE_T* create_javascript_include_tag_element(
1000
1088
  size_t length = pm_string_length(&string_node->unescaped);
1001
1089
  source_value = hb_allocator_strndup(allocator, (const char*) pm_string_source(&string_node->unescaped), length);
1002
1090
  } else {
1003
- size_t source_length = source_argument->location.end - source_argument->location.start;
1004
- source_value = hb_allocator_strndup(allocator, (const char*) source_argument->location.start, source_length);
1091
+ source_value = hb_allocator_strndup(
1092
+ allocator,
1093
+ (const char*) (parse_context->prism_source + source_argument->location.start),
1094
+ source_argument->location.length
1095
+ );
1005
1096
  }
1006
1097
 
1007
1098
  position_T source_start, source_end;
@@ -1108,8 +1199,12 @@ static hb_array_T* transform_javascript_include_tag_multi_source(
1108
1199
 
1109
1200
  if (source_count == 0) { return NULL; }
1110
1201
 
1111
- char* path_options =
1112
- extract_path_options_from_keyword_hash(call_node, JAVASCRIPT_INCLUDE_TAG_PATH_OPTIONS, allocator);
1202
+ char* path_options = extract_path_options_from_keyword_hash(
1203
+ call_node,
1204
+ parse_context->prism_source,
1205
+ JAVASCRIPT_INCLUDE_TAG_PATH_OPTIONS,
1206
+ allocator
1207
+ );
1113
1208
  hb_array_T* elements = hb_array_init(source_count * 2, allocator);
1114
1209
 
1115
1210
  for (size_t i = 0; i < source_count; i++) {
@@ -1208,7 +1303,12 @@ static hb_array_T* transform_stylesheet_link_tag_multi_source(
1208
1303
 
1209
1304
  if (source_count == 0) { return NULL; }
1210
1305
 
1211
- char* path_options = extract_path_options_from_keyword_hash(call_node, STYLESHEET_LINK_TAG_PATH_OPTIONS, allocator);
1306
+ char* path_options = extract_path_options_from_keyword_hash(
1307
+ call_node,
1308
+ parse_context->prism_source,
1309
+ STYLESHEET_LINK_TAG_PATH_OPTIONS,
1310
+ allocator
1311
+ );
1212
1312
  hb_array_T* elements = hb_array_init(source_count * 2, allocator);
1213
1313
 
1214
1314
  for (size_t i = 0; i < source_count; i++) {
@@ -1315,16 +1415,17 @@ static AST_NODE_T* transform_erb_block_to_tag_helper(
1315
1415
  resolve_nonce_attribute(attributes, allocator);
1316
1416
  }
1317
1417
 
1318
- if (detect_link_to(parse_context->info->call_node, &parse_context->parser)
1319
- && parse_context->info->call_node->arguments && parse_context->info->call_node->arguments->arguments.size >= 1) {
1418
+ if (detect_link_to(parse_context->info->call_node, parse_context->parser) && parse_context->info->call_node->arguments
1419
+ && parse_context->info->call_node->arguments->arguments.size >= 1) {
1320
1420
  pm_node_t* first_argument = parse_context->info->call_node->arguments->arguments.nodes[0];
1321
- size_t source_length = first_argument->location.end - first_argument->location.start;
1421
+ size_t source_length = first_argument->location.length;
1422
+ const char* first_argument_source = (const char*) (parse_context->prism_source + first_argument->location.start);
1322
1423
  char* href = NULL;
1323
1424
 
1324
- if (first_argument->type != PM_STRING_NODE && !is_route_helper_node(first_argument, &parse_context->parser)) {
1325
- href = wrap_in_url_for((const char*) first_argument->location.start, source_length, allocator);
1425
+ if (first_argument->type != PM_STRING_NODE && !is_route_helper_node(first_argument, parse_context->parser)) {
1426
+ href = wrap_in_url_for(first_argument_source, source_length, allocator);
1326
1427
  } else {
1327
- href = hb_allocator_strndup(allocator, (const char*) first_argument->location.start, source_length);
1428
+ href = hb_allocator_strndup(allocator, first_argument_source, source_length);
1328
1429
  }
1329
1430
 
1330
1431
  if (href) {
@@ -1350,8 +1451,8 @@ static AST_NODE_T* transform_erb_block_to_tag_helper(
1350
1451
  }
1351
1452
  }
1352
1453
 
1353
- if (detect_turbo_frame_tag(parse_context->info->call_node, &parse_context->parser)) {
1354
- char* id_value = extract_turbo_frame_tag_id(parse_context->info->call_node, &parse_context->parser, allocator);
1454
+ if (detect_turbo_frame_tag(parse_context->info->call_node, parse_context->parser)) {
1455
+ char* id_value = extract_turbo_frame_tag_id(parse_context->info->call_node, parse_context->parser, allocator);
1355
1456
 
1356
1457
  if (id_value) {
1357
1458
  if (!attributes) { attributes = hb_array_init(4, allocator); }
@@ -1519,7 +1620,7 @@ static AST_NODE_T* transform_link_to_helper(
1519
1620
  hb_allocator_T* allocator = context->allocator;
1520
1621
  tag_helper_info_T* info = parse_context->info;
1521
1622
 
1522
- char* href = extract_link_to_href(info->call_node, &parse_context->parser, allocator);
1623
+ char* href = extract_link_to_href(info->call_node, parse_context->parser, allocator);
1523
1624
 
1524
1625
  hb_array_T* attributes = NULL;
1525
1626
  pm_arguments_node_t* link_arguments = info->call_node->arguments;
@@ -1547,8 +1648,12 @@ static AST_NODE_T* transform_link_to_helper(
1547
1648
 
1548
1649
  if (second_arg->type != PM_KEYWORD_HASH_NODE && second_arg->type != PM_HASH_NODE
1549
1650
  && second_arg->type != PM_STRING_NODE && second_arg->type != PM_SYMBOL_NODE) {
1550
- size_t source_length = second_arg->location.end - second_arg->location.start;
1551
- char* content = hb_allocator_strndup(allocator, (const char*) second_arg->location.start, source_length);
1651
+ size_t source_length = second_arg->location.length;
1652
+ char* content = hb_allocator_strndup(
1653
+ allocator,
1654
+ (const char*) (parse_context->prism_source + second_arg->location.start),
1655
+ source_length
1656
+ );
1552
1657
 
1553
1658
  if (content) {
1554
1659
  hb_buffer_T wrapped;
@@ -24,14 +24,15 @@ char* extract_turbo_frame_tag_id(pm_call_node_t* call_node, pm_parser_t* parser,
24
24
  return hb_allocator_strndup(allocator, (const char*) pm_string_source(&symbol_node->unescaped), length);
25
25
  }
26
26
 
27
- size_t source_length = first_argument->location.end - first_argument->location.start;
28
- const char* source = (const char*) first_argument->location.start;
27
+ size_t source_length = first_argument->location.length;
28
+ const char* source = (const char*) (pm_parser_start(parser) + first_argument->location.start);
29
29
 
30
30
  if (first_argument->type == PM_CALL_NODE) {
31
31
  pm_call_node_t* call = (pm_call_node_t*) first_argument;
32
- pm_constant_t* call_constant = pm_constant_pool_id_to_constant(&parser->constant_pool, call->name);
32
+ const pm_constant_t* call_constant = pm_parser_constant(parser, call->name);
33
33
 
34
- if (call_constant && call_constant->length == 6 && strncmp((const char*) call_constant->start, "dom_id", 6) == 0) {
34
+ if (call_constant && pm_constant_length(call_constant) == 6
35
+ && strncmp((const char*) pm_constant_start(call_constant), "dom_id", 6) == 0) {
35
36
  return hb_allocator_strndup(allocator, source, source_length);
36
37
  }
37
38
  }