From 36e916da0c8631cde8f0a17edefab67653ac41b6 Mon Sep 17 00:00:00 2001 From: Lars Hvam <5888506+larshp@users.noreply.github.com> Date: Wed, 8 Apr 2026 07:50:34 +0200 Subject: [PATCH 1/2] add testcase --- src/zcl_mjs.clas.testclasses.abap | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/zcl_mjs.clas.testclasses.abap b/src/zcl_mjs.clas.testclasses.abap index 6dbe7f9..22de31a 100644 --- a/src/zcl_mjs.clas.testclasses.abap +++ b/src/zcl_mjs.clas.testclasses.abap @@ -105,6 +105,7 @@ CLASS ltcl_test DEFINITION FOR TESTING METHODS test_date_now FOR TESTING RAISING zcx_mjs_runtime. METHODS test_array_map FOR TESTING RAISING zcx_mjs_runtime. METHODS test_rest_map FOR TESTING RAISING zcx_mjs_runtime. + METHODS test_replace_regex_anchor FOR TESTING RAISING zcx_mjs_runtime. METHODS test262 FOR TESTING RAISING zcx_mjs_runtime. @@ -902,6 +903,12 @@ CLASS ltcl_test IMPLEMENTATION. exp = |2 3| ). ENDMETHOD. + METHOD test_replace_regex_anchor. + cl_abap_unit_assert=>assert_equals( + act = trim( zcl_mjs=>eval( `console.log("abc".replace(/^/g, "x"));` ) ) + exp = |xabc| ). + ENDMETHOD. + METHOD test262. DATA(lv_nl) = cl_abap_char_utilities=>newline. DATA(lv_js) = From 263f55cb9a1be48f6590235340182b8304ceda9f Mon Sep 17 00:00:00 2001 From: Lars Hvam <5888506+larshp@users.noreply.github.com> Date: Wed, 8 Apr 2026 08:55:11 +0200 Subject: [PATCH 2/2] wip --- package-lock.json | 16 ++++++++-------- package.json | 4 ++-- src/zcl_mjs.clas.abap | 40 +++++++++++++++++++++------------------- 3 files changed, 31 insertions(+), 29 deletions(-) diff --git a/package-lock.json b/package-lock.json index 244eae4..10e1c79 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,8 +10,8 @@ "license": "MIT", "dependencies": { "@abaplint/cli": "^2.118.10", - "@abaplint/runtime": "^2.13.9", - "@abaplint/transpiler-cli": "^2.13.9" + "@abaplint/runtime": "^2.13.10", + "@abaplint/transpiler-cli": "^2.13.10" } }, "node_modules/@abaplint/cli": { @@ -30,9 +30,9 @@ } }, "node_modules/@abaplint/runtime": { - "version": "2.13.9", - "resolved": "https://registry.npmjs.org/@abaplint/runtime/-/runtime-2.13.9.tgz", - "integrity": "sha512-5c+8iSjCkIH27HqsjQQf/lfNfQ+ZvUSIWRcAn7pDdak3XB3Uq17Svfq1UPMLV8PGkitNTnbwLZnTdLSbIPwVyQ==", + "version": "2.13.10", + "resolved": "https://registry.npmjs.org/@abaplint/runtime/-/runtime-2.13.10.tgz", + "integrity": "sha512-tlbdT7bqQaLUF6kbk9uzObIP54DhLeOpB3rLCcXsxvCECc3pQWSs0Uxw4zPycuuvtSXF3jf3xMvkXKaHTHMzEA==", "license": "MIT", "dependencies": { "temporal-polyfill": "^0.3.2" @@ -42,9 +42,9 @@ } }, "node_modules/@abaplint/transpiler-cli": { - "version": "2.13.9", - "resolved": "https://registry.npmjs.org/@abaplint/transpiler-cli/-/transpiler-cli-2.13.9.tgz", - "integrity": "sha512-uUfXQC+gN1JBYmlESW4ngnloq216o7C1zVN0pApkxjWC3lTkdkSPC0GbaEEFfbd4jK8Aw+pUHg52r0ag44eNtw==", + "version": "2.13.10", + "resolved": "https://registry.npmjs.org/@abaplint/transpiler-cli/-/transpiler-cli-2.13.10.tgz", + "integrity": "sha512-Zxy6YwuvjoqvMbN0PnhGp3gSjOliEVcXIna9V36SDq3Atnd4YPEvJZw09JiQQOOOXs3fkU7WyG6d9iN6DG0lUg==", "license": "MIT", "bin": { "abap_transpile": "abap_transpile" diff --git a/package.json b/package.json index 6d83557..2ded7e0 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "homepage": "https://github.com/larshp/zmjs#readme", "dependencies": { "@abaplint/cli": "^2.118.10", - "@abaplint/runtime": "^2.13.9", - "@abaplint/transpiler-cli": "^2.13.9" + "@abaplint/runtime": "^2.13.10", + "@abaplint/transpiler-cli": "^2.13.10" } } diff --git a/src/zcl_mjs.clas.abap b/src/zcl_mjs.clas.abap index 922467a..702667d 100644 --- a/src/zcl_mjs.clas.abap +++ b/src/zcl_mjs.clas.abap @@ -3014,27 +3014,29 @@ CLASS zcl_mjs IMPLEMENTATION. IF lv_rxint = 2 OR lv_rxint = 3. lv_rxicase = abap_true. ENDIF. CLEAR lv_rxout. lv_rxrem = is_obj-str. - DO. - IF lv_rxicase = abap_true. - FIND FIRST OCCURRENCE OF REGEX ls_rep1-str IN lv_rxrem - MATCH OFFSET lv_rxoff MATCH LENGTH lv_rxmln IGNORING CASE. - ELSE. - FIND FIRST OCCURRENCE OF REGEX ls_rep1-str IN lv_rxrem - MATCH OFFSET lv_rxoff MATCH LENGTH lv_rxmln. - ENDIF. - IF sy-subrc <> 0. EXIT. ENDIF. - IF lv_rxoff > 0. - lv_rxout = lv_rxout && substring( val = lv_rxrem len = lv_rxoff ). + IF lv_rxicase = abap_true. + FIND ALL OCCURRENCES OF REGEX ls_rep1-str IN lv_rxrem + RESULTS DATA(lt_rx_res) IGNORING CASE. + ELSE. + FIND ALL OCCURRENCES OF REGEX ls_rep1-str IN lv_rxrem + RESULTS lt_rx_res. + ENDIF. + IF lv_rxglob = abap_false AND lines( lt_rx_res ) > 1. + DELETE lt_rx_res FROM 2. + ENDIF. + DATA lv_rx_pos TYPE i. + lv_rx_pos = 0. + LOOP AT lt_rx_res ASSIGNING FIELD-SYMBOL(). + IF -offset > lv_rx_pos. + lv_rxout = lv_rxout && substring( val = lv_rxrem off = lv_rx_pos len = -offset - lv_rx_pos ). ENDIF. lv_rxout = lv_rxout && lv_rep_to. - lv_rxnxt = lv_rxoff + lv_rxmln. - IF lv_rxnxt >= strlen( lv_rxrem ). - CLEAR lv_rxrem. - EXIT. - ENDIF. - lv_rxrem = substring( val = lv_rxrem off = lv_rxnxt ). - IF lv_rxglob = abap_false. EXIT. ENDIF. - ENDDO. + lv_rx_pos = -offset + -length. + ENDLOOP. + IF lv_rx_pos < strlen( lv_rxrem ). + lv_rxout = lv_rxout && substring( val = lv_rxrem off = lv_rx_pos ). + ENDIF. + CLEAR lv_rxrem. lv_rxout = lv_rxout && lv_rxrem. rs_val = string_val( lv_rxout ). ELSE.