@@ -4072,12 +4072,15 @@ private Object js_SymbolReplace(
40724072 Object replaceValue = args .length > 1 ? args [1 ] : Undefined .instance ;
40734073 boolean functionalReplace = replaceValue instanceof Callable ;
40744074 List <ReplacementOperation > replaceOps ;
4075+ Callable replaceFn ;
40754076
40764077 if (!functionalReplace ) {
4078+ replaceFn = null ;
40774079 replaceOps =
40784080 AbstractEcmaStringOperations .buildReplacementList (
40794081 ScriptRuntime .toString (replaceValue ));
40804082 } else {
4083+ replaceFn = (Callable ) replaceValue ;
40814084 replaceOps = List .of ();
40824085 }
40834086 String flags = ScriptRuntime .toString (ScriptRuntime .getObjectProp (thisObj , "flags" , cx ));
@@ -4138,40 +4141,26 @@ private Object js_SymbolReplace(
41384141 }
41394142
41404143 Object namedCaptures = ScriptRuntime .getObjectProp (result , "groups" , cx , scope );
4141- String replacementString ;
4142-
4143- if (functionalReplace ) {
4144- List <Object > replacerArgs = new ArrayList <>();
4145- replacerArgs .add (matched );
4146- replacerArgs .addAll (captures );
4147- replacerArgs .add (position );
4148- replacerArgs .add (s );
4149- if (!Undefined .isUndefined (namedCaptures )) {
4150- replacerArgs .add (namedCaptures );
4151- }
4152-
4153- Scriptable callThis =
4154- ScriptRuntime .getApplyOrCallThis (
4155- cx , scope , null , 0 , (Callable ) replaceValue );
4156- Object replacementValue =
4157- ((Callable ) replaceValue ).call (cx , scope , callThis , replacerArgs .toArray ());
4158- replacementString = ScriptRuntime .toString (replacementValue );
4159- } else {
4160- if (!Undefined .isUndefined (namedCaptures )) {
4161- namedCaptures = ScriptRuntime .toObject (scope , namedCaptures );
4162- }
4163-
4164- replacementString =
4165- AbstractEcmaStringOperations .getSubstitution (
4166- cx ,
4167- scope ,
4168- matched ,
4169- s ,
4170- position ,
4171- captures ,
4172- namedCaptures ,
4173- replaceOps );
4174- }
4144+ String replacementString =
4145+ functionalReplace
4146+ ? makeComplexReplacement (
4147+ cx ,
4148+ scope ,
4149+ matched ,
4150+ captures ,
4151+ position ,
4152+ s ,
4153+ namedCaptures ,
4154+ replaceFn )
4155+ : makeSimpleReplacement (
4156+ cx ,
4157+ scope ,
4158+ matched ,
4159+ captures ,
4160+ position ,
4161+ s ,
4162+ namedCaptures ,
4163+ replaceOps );
41754164
41764165 if (position >= nextSourcePosition ) {
41774166 accumulatedResult .append (s , nextSourcePosition , position );
@@ -4188,6 +4177,51 @@ private Object js_SymbolReplace(
41884177 }
41894178 }
41904179
4180+ private String makeComplexReplacement (
4181+ Context cx ,
4182+ Scriptable scope ,
4183+ String matched ,
4184+ List <?> captures ,
4185+ int position ,
4186+ String s ,
4187+ Object namedCaptures ,
4188+ Callable replaceFunction ) {
4189+ Object [] replacerArgs =
4190+ new Object [1 + captures .size () + (Undefined .isUndefined (namedCaptures ) ? 2 : 3 )];
4191+ replacerArgs [0 ] = matched ;
4192+ int i = 1 ;
4193+ for (; i <= captures .size (); i ++) {
4194+ var capture = captures .get (i - 1 );
4195+ replacerArgs [i ] = capture == null ? Undefined .instance : capture ;
4196+ }
4197+ replacerArgs [i ++] = position ;
4198+ replacerArgs [i ++] = s ;
4199+ if (!Undefined .isUndefined (namedCaptures )) {
4200+ replacerArgs [i ++] = namedCaptures ;
4201+ }
4202+
4203+ Scriptable callThis = ScriptRuntime .getApplyOrCallThis (cx , scope , null , 0 , replaceFunction );
4204+ Object replacementValue = replaceFunction .call (cx , scope , callThis , replacerArgs );
4205+ return ScriptRuntime .toString (replacementValue );
4206+ }
4207+
4208+ private String makeSimpleReplacement (
4209+ Context cx ,
4210+ Scriptable scope ,
4211+ String matched ,
4212+ List <?> captures ,
4213+ int position ,
4214+ String s ,
4215+ Object namedCaptures ,
4216+ List <ReplacementOperation > replaceOps ) {
4217+ if (!Undefined .isUndefined (namedCaptures )) {
4218+ namedCaptures = ScriptRuntime .toObject (scope , namedCaptures );
4219+ }
4220+
4221+ return AbstractEcmaStringOperations .getSubstitution (
4222+ cx , scope , matched , s , position , captures , namedCaptures , replaceOps );
4223+ }
4224+
41914225 private Object js_SymbolSplit (Context cx , Scriptable scope , Scriptable rx , Object [] args ) {
41924226 // See ECMAScript spec 22.2.6.14
41934227 if (!ScriptRuntime .isObject (rx )) {
0 commit comments