@@ -1022,13 +1022,17 @@ public void init() { // not in constructor because it has to be on Runnable.run(
1022
1022
runtime .magicVariables .forEach ((k , v ) -> {
1023
1023
// even hidden variables may need pre-processing
1024
1024
// for e.g. the __arg may contain functions that originated in a different js context
1025
- Object o = recurseAndAttach (k , v , seen );
1026
- if (o == null ) {
1027
- o = v ;
1028
- }
1029
- JS .put (k , o );
1025
+ AttachResult ar = recurseAndAttach (k , v , seen );
1026
+ JS .put (k , ar .value );
1027
+ });
1028
+ // re-hydrate any functions from caller or background
1029
+ vars .forEach ((k , v ) -> {
1030
+ AttachResult ar = recurseAndAttach (k , v .getValue (), seen );
1031
+ // note that we don't update the vars !
1032
+ // if we do, any "bad" out-of-context values will crash the constructor of Variable
1033
+ // it is possible the vars are detached / re-used later, so we kind of defer the inevitable
1034
+ JS .put (k , ar .value );
1030
1035
});
1031
- attachVariables (seen ); // re-hydrate any functions from caller or background
1032
1036
JS .put (KARATE , bridge );
1033
1037
JS .put (READ , readFunction );
1034
1038
HttpClient client = runtime .featureRuntime .suite .clientFactory .create (this );
@@ -1049,22 +1053,6 @@ public void init() { // not in constructor because it has to be on Runnable.run(
1049
1053
}
1050
1054
}
1051
1055
1052
- private void attachVariables (Set <Object > seen ) {
1053
- vars .forEach ((k , v ) -> {
1054
- Object o = recurseAndAttach (k , v .getValue (), seen );
1055
- if (o == null ) {
1056
- o = v .getValue ();
1057
- } else {
1058
- try {
1059
- vars .put (k , new Variable (o ));
1060
- } catch (Exception e ) {
1061
- logger .debug ("[*** attach variables ***] ignoring non-json value: '{}' - {}" , k , e .getMessage ());
1062
- }
1063
- }
1064
- JS .put (k , o );
1065
- });
1066
- }
1067
-
1068
1056
protected Map <String , Variable > detachVariables () {
1069
1057
Set <Object > seen = Collections .newSetFromMap (new IdentityHashMap ());
1070
1058
Map <String , Variable > detached = new HashMap (vars .size ());
@@ -1075,53 +1063,76 @@ protected Map<String, Variable> detachVariables() {
1075
1063
return detached ;
1076
1064
}
1077
1065
1078
- private Object recurseAndAttach (String name , Object o , Set <Object > seen ) {
1066
+ private static class AttachResult {
1067
+
1068
+ final Object value ;
1069
+ final boolean dirty ;
1070
+
1071
+ static final AttachResult NULL = new AttachResult (null , true );
1072
+
1073
+ AttachResult (Object value , boolean dirty ) {
1074
+ this .value = value ;
1075
+ this .dirty = dirty ;
1076
+ }
1077
+
1078
+ static AttachResult dirty (Object value ) {
1079
+ return new AttachResult (value , true );
1080
+ }
1081
+
1082
+ static AttachResult clean (Object value ) {
1083
+ return new AttachResult (value , false );
1084
+ }
1085
+
1086
+ }
1087
+
1088
+ private AttachResult recurseAndAttach (String name , Object o , Set <Object > seen ) {
1079
1089
if (o instanceof Value ) {
1090
+ Value value = Value .asValue (o );
1080
1091
try {
1081
- Value value = Value .asValue (o );
1082
1092
if (value .canExecute () && value .isMetaObject ()) { // js function
1083
- return attach (value );
1093
+ return AttachResult . dirty ( attach (value ) );
1084
1094
} else { // anything else, including java functions and java-type references
1085
- return value ;
1095
+ return AttachResult . dirty ( value ) ;
1086
1096
}
1087
1097
} catch (Exception e ) {
1088
1098
logger .warn ("[*** attach ***] ignoring non-json value: '{}' - {}" , name , e .getMessage ());
1089
- return null ;
1099
+ // here we sweep things under the carpet and hope that graal does not notice !
1100
+ return AttachResult .dirty (value );
1090
1101
}
1091
1102
} else if (o instanceof JsFunction ) {
1092
1103
JsFunction jf = (JsFunction ) o ;
1093
1104
try {
1094
- return attachSource (jf .source );
1105
+ return AttachResult . dirty ( attachSource (jf .source ) );
1095
1106
} catch (Exception e ) {
1096
1107
logger .warn ("[*** attach ***] ignoring js-function: '{}' - {}" , name , e .getMessage ());
1097
- return null ;
1098
- }
1108
+ return AttachResult . NULL ;
1109
+ }
1099
1110
} else if (o instanceof List ) {
1100
1111
if (seen .add (o )) {
1101
1112
List list = (List ) o ;
1102
1113
int count = list .size ();
1103
1114
for (int i = 0 ; i < count ; i ++) {
1104
1115
Object child = list .get (i );
1105
- Object result = recurseAndAttach (name + "[" + i + "]" , child , seen );
1106
- if (result != null ) {
1107
- list .set (i , result );
1116
+ AttachResult ar = recurseAndAttach (name + "[" + i + "]" , child , seen );
1117
+ if (ar . dirty ) {
1118
+ list .set (i , ar . value );
1108
1119
}
1109
1120
}
1110
1121
}
1111
- return null ;
1122
+ return AttachResult . clean ( o ) ;
1112
1123
} else if (o instanceof Map ) {
1113
1124
if (seen .add (o )) {
1114
1125
Map <String , Object > map = (Map ) o ;
1115
1126
map .forEach ((k , v ) -> {
1116
- Object result = recurseAndAttach (name + "." + k , v , seen );
1117
- if (result != null ) {
1118
- map .put (k , result );
1127
+ AttachResult ar = recurseAndAttach (name + "." + k , v , seen );
1128
+ if (ar . dirty ) {
1129
+ map .put (k , ar . value );
1119
1130
}
1120
1131
});
1121
1132
}
1122
- return null ;
1133
+ return AttachResult . clean ( o ) ;
1123
1134
} else {
1124
- return null ;
1135
+ return AttachResult . clean ( o ) ;
1125
1136
}
1126
1137
}
1127
1138
@@ -1146,7 +1157,7 @@ private Object recurseAndAttachAndDeepClone(String name, Object o, Set<Object> s
1146
1157
return attachSource (jf .source );
1147
1158
} catch (Exception e ) {
1148
1159
logger .warn ("[*** attach deep ***] ignoring js-function: '{}' - {}" , name , e .getMessage ());
1149
- return null ;
1160
+ return null ;
1150
1161
}
1151
1162
} else if (o instanceof List ) {
1152
1163
if (seen .add (o )) {
0 commit comments