@@ -186,13 +186,23 @@ JsAstNode* build_js_literal(JsTranspiler* tp, TSNode literal_node) {
186186 break ;
187187 }
188188 }
189- // Create null-terminated string for strtod
189+ // Create null-terminated string, stripping numeric separators (_)
190190 char * temp_str = (char *)malloc (source.length + 1 );
191191 if (temp_str) {
192- memcpy (temp_str, source.str , source.length );
193- temp_str[source.length ] = ' \0 ' ;
192+ size_t j = 0 ;
193+ for (size_t i = 0 ; i < source.length ; i++) {
194+ if (source.str [i] != ' _' ) temp_str[j++] = source.str [i];
195+ }
196+ temp_str[j] = ' \0 ' ;
194197 char * endptr;
195- literal->value .number_value = strtod (temp_str, &endptr);
198+ // strtod handles decimal and 0x hex, but not 0b binary or 0o octal
199+ if (j > 2 && temp_str[0 ] == ' 0' && (temp_str[1 ] == ' b' || temp_str[1 ] == ' B' )) {
200+ literal->value .number_value = (double )strtoull (temp_str + 2 , &endptr, 2 );
201+ } else if (j > 2 && temp_str[0 ] == ' 0' && (temp_str[1 ] == ' o' || temp_str[1 ] == ' O' )) {
202+ literal->value .number_value = (double )strtoull (temp_str + 2 , &endptr, 8 );
203+ } else {
204+ literal->value .number_value = strtod (temp_str, &endptr);
205+ }
196206 free (temp_str);
197207 } else {
198208 literal->value .number_value = 0.0 ;
@@ -555,17 +565,35 @@ JsAstNode* build_js_member_expression(JsTranspiler* tp, TSNode member_node) {
555565JsAstNode* build_js_array_expression (JsTranspiler* tp, TSNode array_node) {
556566 JsArrayNode* array = (JsArrayNode*)alloc_js_ast_node (tp, JS_AST_NODE_ARRAY_EXPRESSION , array_node, sizeof (JsArrayNode));
557567
558- uint32_t element_count = ts_node_named_child_count (array_node);
559- array-> length = element_count ;
568+ // v18: Use all children (including unnamed commas) to correctly handle elisions [1,,3]
569+ uint32_t total_children = ts_node_child_count (array_node) ;
560570
561571 JsAstNode* prev_element = NULL ;
562572 uint32_t actual_count = 0 ;
563- for (uint32_t i = 0 ; i < element_count; i++) {
564- TSNode element_node = ts_node_named_child (array_node, i);
565- const char * child_type = ts_node_type (element_node);
573+ bool expect_elem = true ; // true = next non-comma token should be an element
574+ for (uint32_t i = 0 ; i < total_children; i++) {
575+ TSNode child = ts_node_child (array_node, i);
576+ const char * child_type = ts_node_type (child);
577+ if (strcmp (child_type, " [" ) == 0 || strcmp (child_type, " ]" ) == 0 ) continue ;
578+ if (strcmp (child_type, " ," ) == 0 ) {
579+ if (expect_elem) {
580+ // consecutive comma or leading comma = elision: insert undefined hole
581+ JsAstNode* elision = (JsAstNode*)alloc_js_ast_node (
582+ tp, JS_AST_NODE_NULL , child, sizeof (JsAstNode));
583+ elision->type = &TYPE_ANY ;
584+ if (!prev_element) array->elements = elision;
585+ else prev_element->next = elision;
586+ prev_element = elision;
587+ actual_count++;
588+ } else {
589+ expect_elem = true ;
590+ }
591+ continue ;
592+ }
566593 // skip comment nodes inside array literals
567594 if (strcmp (child_type, " comment" ) == 0 ) continue ;
568- JsAstNode* element = build_js_expression (tp, element_node);
595+ expect_elem = false ;
596+ JsAstNode* element = build_js_expression (tp, child);
569597 if (!element) continue ;
570598
571599 if (!prev_element) {
@@ -2186,18 +2214,14 @@ JsAstNode* build_js_switch_statement(JsTranspiler* tp, TSNode switch_node) {
21862214 // Get consequent statements
21872215 JsAstNode* prev_stmt = NULL ;
21882216 uint32_t stmt_count = ts_node_named_child_count (child);
2217+ // Determine position of the value node so we can skip it in the body
2218+ TSNode case_value = ts_node_child_by_field_name (child, " value" , strlen (" value" ));
2219+ uint32_t value_start = ts_node_is_null (case_value) ? UINT32_MAX : ts_node_start_byte (case_value);
21892220 for (uint32_t j = 0 ; j < stmt_count; j++) {
21902221 TSNode stmt_child = ts_node_named_child (child, j);
2191- const char * stmt_type = ts_node_type (stmt_child);
2192- // Skip the value node itself
2193- if (strcmp (stmt_type, " number" ) == 0 || strcmp (stmt_type, " string" ) == 0 ||
2194- strcmp (stmt_type, " identifier" ) == 0 || strcmp (stmt_type, " true" ) == 0 ||
2195- strcmp (stmt_type, " false" ) == 0 ) {
2196- // Check if this is the case value by position
2197- TSNode value = ts_node_child_by_field_name (child, " value" , strlen (" value" ));
2198- if (!ts_node_is_null (value) && ts_node_start_byte (stmt_child) == ts_node_start_byte (value)) {
2199- continue ;
2200- }
2222+ // Skip the value node itself (any expression type)
2223+ if (ts_node_start_byte (stmt_child) == value_start) {
2224+ continue ;
22012225 }
22022226 JsAstNode* stmt = build_js_statement (tp, stmt_child);
22032227 if (!stmt) continue ;
@@ -2409,6 +2433,7 @@ JsAstNode* build_js_field_definition(JsTranspiler* tp, TSNode field_node) {
24092433 tp, JS_AST_NODE_FIELD_DEFINITION , field_node, sizeof (JsFieldDefinitionNode));
24102434 field->is_static = false ;
24112435 field->is_private = false ;
2436+ field->computed = false ;
24122437 field->key = NULL ;
24132438 field->value = NULL ;
24142439
@@ -2430,6 +2455,9 @@ JsAstNode* build_js_field_definition(JsTranspiler* tp, TSNode field_node) {
24302455 if (strcmp (prop_type, " private_property_identifier" ) == 0 ) {
24312456 field->is_private = true ;
24322457 }
2458+ if (strcmp (prop_type, " computed_property_name" ) == 0 ) {
2459+ field->computed = true ;
2460+ }
24332461 field->key = build_js_expression (tp, prop_node);
24342462 }
24352463
@@ -2456,6 +2484,16 @@ JsAstNode* build_js_class_body(JsTranspiler* tp, TSNode body_node) {
24562484 JsAstNode* method = NULL ;
24572485 if (strcmp (child_type, " field_definition" ) == 0 ) {
24582486 method = build_js_field_definition (tp, child_node);
2487+ } else if (strcmp (child_type, " class_static_block" ) == 0 ) {
2488+ // static { ... } block
2489+ JsStaticBlockNode* sb = (JsStaticBlockNode*)alloc_js_ast_node (
2490+ tp, JS_AST_NODE_STATIC_BLOCK , child_node, sizeof (JsStaticBlockNode));
2491+ sb->body = NULL ;
2492+ TSNode body_node = ts_node_child_by_field_name (child_node, " body" , strlen (" body" ));
2493+ if (!ts_node_is_null (body_node)) {
2494+ sb->body = build_js_block_statement (tp, body_node);
2495+ }
2496+ method = (JsAstNode*)sb;
24592497 } else {
24602498 method = build_js_method_definition (tp, child_node);
24612499 }
0 commit comments