Skip to content

Commit 238594e

Browse files
authored
bugfix replace() (#66)
* add testcases * add testcase * hmm * Delete .bash_profile * Delete .claude/agents * Delete .claude/commands * Delete .bashrc * Delete .gitconfig * Delete .gitmodules * Delete .idea * Delete .mcp.json * Delete .profile * Delete .ripgreprc * Delete .vscode * Delete .zprofile * Delete .zshrc * Delete fix_replace.sh * Delete test.mjs * Delete test2.mjs * update * fix for real * rm testcase
1 parent 3d408b5 commit 238594e

4 files changed

Lines changed: 85 additions & 25 deletions

File tree

package-lock.json

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"homepage": "https://github.com/larshp/zmjs#readme",
1919
"dependencies": {
2020
"@abaplint/cli": "^2.118.10",
21-
"@abaplint/runtime": "^2.13.10",
22-
"@abaplint/transpiler-cli": "^2.13.10"
21+
"@abaplint/runtime": "^2.13.11",
22+
"@abaplint/transpiler-cli": "^2.13.11"
2323
}
2424
}

src/zcl_mjs.clas.abap

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3014,27 +3014,68 @@ CLASS zcl_mjs IMPLEMENTATION.
30143014
IF lv_rxint = 2 OR lv_rxint = 3. lv_rxicase = abap_true. ENDIF.
30153015
CLEAR lv_rxout.
30163016
lv_rxrem = is_obj-str.
3017-
IF lv_rxicase = abap_true.
3018-
FIND ALL OCCURRENCES OF REGEX ls_rep1-str IN lv_rxrem
3019-
RESULTS DATA(lt_rx_res) IGNORING CASE.
3017+
DATA lv_rx_pos TYPE i VALUE 0.
3018+
DATA lt_rx_res TYPE match_result_tab.
3019+
IF strlen( ls_rep1-str ) = 0.
3020+
" Empty regex matches empty string between everywhere
3021+
DO.
3022+
IF lv_rx_pos > strlen( lv_rxrem ). EXIT. ENDIF.
3023+
DATA ls_e_res TYPE match_result.
3024+
ls_e_res-offset = lv_rx_pos.
3025+
ls_e_res-length = 0.
3026+
APPEND ls_e_res TO lt_rx_res.
3027+
lv_rx_pos = lv_rx_pos + 1.
3028+
IF lv_rxglob = abap_false OR lv_rx_pos > strlen( lv_rxrem ).
3029+
EXIT.
3030+
ENDIF.
3031+
ENDDO.
30203032
ELSE.
3021-
FIND ALL OCCURRENCES OF REGEX ls_rep1-str IN lv_rxrem
3022-
RESULTS lt_rx_res.
3023-
ENDIF.
3024-
IF lv_rxglob = abap_false AND lines( lt_rx_res ) > 1.
3025-
DELETE lt_rx_res FROM 2.
3033+
DO.
3034+
IF lv_rx_pos > strlen( lv_rxrem ). EXIT. ENDIF.
3035+
DATA ls_rx_res TYPE match_result.
3036+
IF lv_rxicase = abap_true.
3037+
FIND REGEX ls_rep1-str IN SECTION OFFSET lv_rx_pos OF lv_rxrem
3038+
MATCH OFFSET ls_rx_res-offset
3039+
MATCH LENGTH ls_rx_res-length
3040+
IGNORING CASE.
3041+
ELSE.
3042+
FIND REGEX ls_rep1-str IN SECTION OFFSET lv_rx_pos OF lv_rxrem
3043+
MATCH OFFSET ls_rx_res-offset
3044+
MATCH LENGTH ls_rx_res-length.
3045+
ENDIF.
3046+
IF sy-subrc <> 0.
3047+
EXIT.
3048+
ENDIF.
3049+
IF lv_rx_pos > 0 AND ls_rx_res-offset = lv_rx_pos AND ls_rx_res-length = 0 AND substring( val = ls_rep1-str len = 1 ) = '^'.
3050+
lv_rx_pos = lv_rx_pos + 1.
3051+
CONTINUE.
3052+
ENDIF.
3053+
APPEND ls_rx_res TO lt_rx_res.
3054+
IF lv_rxglob = abap_false.
3055+
EXIT.
3056+
ENDIF.
3057+
IF ls_rx_res-length = 0.
3058+
lv_rx_pos = ls_rx_res-offset + 1.
3059+
" Hack for open-abap: ^ matches start of section, which means we might get infinite exact zero-length hits if we keep searching from lv_rx_pos. But wait! We just incremented lv_rx_pos!
3060+
ELSE.
3061+
lv_rx_pos = ls_rx_res-offset + ls_rx_res-length.
3062+
ENDIF.
3063+
IF lv_rx_pos > strlen( lv_rxrem ).
3064+
EXIT.
3065+
ENDIF.
3066+
ENDDO.
30263067
ENDIF.
3027-
DATA lv_rx_pos TYPE i.
3028-
lv_rx_pos = 0.
3068+
DATA lv_rx_pos2 TYPE i.
3069+
lv_rx_pos2 = 0.
30293070
LOOP AT lt_rx_res ASSIGNING FIELD-SYMBOL(<ls_rx_r>).
3030-
IF <ls_rx_r>-offset > lv_rx_pos.
3031-
lv_rxout = lv_rxout && substring( val = lv_rxrem off = lv_rx_pos len = <ls_rx_r>-offset - lv_rx_pos ).
3071+
IF <ls_rx_r>-offset > lv_rx_pos2.
3072+
lv_rxout = lv_rxout && substring( val = lv_rxrem off = lv_rx_pos2 len = <ls_rx_r>-offset - lv_rx_pos2 ).
30323073
ENDIF.
30333074
lv_rxout = lv_rxout && lv_rep_to.
3034-
lv_rx_pos = <ls_rx_r>-offset + <ls_rx_r>-length.
3075+
lv_rx_pos2 = <ls_rx_r>-offset + <ls_rx_r>-length.
30353076
ENDLOOP.
3036-
IF lv_rx_pos < strlen( lv_rxrem ).
3037-
lv_rxout = lv_rxout && substring( val = lv_rxrem off = lv_rx_pos ).
3077+
IF lv_rx_pos2 < strlen( lv_rxrem ).
3078+
lv_rxout = lv_rxout && substring( val = lv_rxrem off = lv_rx_pos2 ).
30383079
ENDIF.
30393080
CLEAR lv_rxrem.
30403081
lv_rxout = lv_rxout && lv_rxrem.

src/zcl_mjs.clas.testclasses.abap

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ CLASS ltcl_test DEFINITION FOR TESTING
106106
METHODS test_array_map FOR TESTING RAISING zcx_mjs_runtime.
107107
METHODS test_rest_map FOR TESTING RAISING zcx_mjs_runtime.
108108
METHODS test_replace_regex_anchor FOR TESTING RAISING zcx_mjs_runtime.
109+
METHODS test_replace_empty_regex FOR TESTING RAISING zcx_mjs_runtime.
110+
METHODS test_replace_empty_regex_g FOR TESTING RAISING zcx_mjs_runtime.
109111

110112
METHODS test262 FOR TESTING RAISING zcx_mjs_runtime.
111113

@@ -909,6 +911,23 @@ CLASS ltcl_test IMPLEMENTATION.
909911
exp = |xabc| ).
910912
ENDMETHOD.
911913

914+
METHOD test_replace_empty_regex.
915+
DATA(lv_nl) = cl_abap_char_utilities=>newline.
916+
DATA(lv_js) =
917+
`var str = "abc";` && lv_nl &&
918+
`var res = str.replace(new RegExp(""), "-");` && lv_nl &&
919+
`console.log(res);`.
920+
cl_abap_unit_assert=>assert_equals(
921+
act = trim( zcl_mjs=>eval( lv_js ) )
922+
exp = |-abc| ).
923+
ENDMETHOD.
924+
925+
METHOD test_replace_empty_regex_g.
926+
cl_abap_unit_assert=>assert_equals(
927+
act = trim( zcl_mjs=>eval( `console.log("abc".replace(/(?:)/g, "-"));` ) )
928+
exp = |-a-b-c-| ).
929+
ENDMETHOD.
930+
912931
METHOD test262.
913932
DATA(lv_nl) = cl_abap_char_utilities=>newline.
914933
DATA(lv_js) =

0 commit comments

Comments
 (0)