4545import java .util .List ;
4646import java .util .Map ;
4747
48+ import org .graalvm .collections .EconomicMap ;
49+ import org .graalvm .collections .UnmodifiableEconomicMap ;
50+
51+ import com .oracle .truffle .api .CompilerAsserts ;
4852import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
4953import com .oracle .truffle .api .frame .FrameDescriptor ;
5054import com .oracle .truffle .api .frame .FrameSlotKind ;
5155import com .oracle .truffle .api .frame .MaterializedFrame ;
5256import com .oracle .truffle .api .nodes .Node ;
5357import com .oracle .truffle .api .object .Shape ;
5458import com .oracle .truffle .api .strings .TruffleString ;
55- import com .oracle .truffle .js .runtime .Boundaries ;
5659import com .oracle .truffle .js .runtime .Errors ;
5760import com .oracle .truffle .js .runtime .JSContext ;
5861import com .oracle .truffle .js .runtime .JSFrameUtil ;
@@ -100,14 +103,19 @@ public static JSModuleRecord getModule(JSDynamicObject obj) {
100103 * object. The list is ordered as if an Array of those String values had been sorted using
101104 * Array.prototype.sort using SortCompare as comparefn.
102105 */
103- public static Map <TruffleString , ExportResolution > getExports (JSDynamicObject obj ) {
106+ public static UnmodifiableEconomicMap <TruffleString , ExportResolution > getExports (JSDynamicObject obj ) {
104107 assert isJSModuleNamespace (obj );
105108 return ((JSModuleNamespaceObject ) obj ).getExports ();
106109 }
107110
108- public static JSModuleNamespaceObject create (JSContext context , JSRealm realm , JSModuleRecord module , Map <TruffleString , ExportResolution > exports ) {
111+ public static JSModuleNamespaceObject create (JSContext context , JSRealm realm , JSModuleRecord module , List <Map .Entry <TruffleString , ExportResolution >> sortedExports ) {
112+ CompilerAsserts .neverPartOfCompilation ();
113+ EconomicMap <TruffleString , ExportResolution > exportResolutionMap = EconomicMap .create (sortedExports .size ());
114+ for (Map .Entry <TruffleString , ExportResolution > entry : sortedExports ) {
115+ exportResolutionMap .put (entry .getKey (), entry .getValue ());
116+ }
109117 JSObjectFactory factory = context .getModuleNamespaceFactory ();
110- JSModuleNamespaceObject obj = JSModuleNamespaceObject .create (realm , factory , module , exports );
118+ JSModuleNamespaceObject obj = JSModuleNamespaceObject .create (realm , factory , module , exportResolutionMap );
111119 assert !JSObject .isExtensible (obj );
112120 return context .trackAllocation (obj );
113121 }
@@ -145,8 +153,7 @@ public Object getOwnHelper(JSDynamicObject store, Object thisObj, Object key, No
145153 if (!Strings .isTString (key )) {
146154 return super .getOwnHelper (store , thisObj , key , encapsulatingNode );
147155 }
148- Map <TruffleString , ExportResolution > exports = getExports (store );
149- ExportResolution binding = exports .get (key );
156+ ExportResolution binding = getExports (store ).get ((TruffleString ) key );
150157 if (binding != null ) {
151158 return getBindingValue (binding );
152159 } else {
@@ -155,6 +162,7 @@ public Object getOwnHelper(JSDynamicObject store, Object thisObj, Object key, No
155162 }
156163
157164 static Object getBindingValue (ExportResolution binding ) {
165+ CompilerAsserts .neverPartOfCompilation ();
158166 TruffleString bindingName = binding .getBindingName ();
159167 JSModuleRecord targetModule = binding .getModule ();
160168 MaterializedFrame targetEnv = targetModule .getEnvironment ();
@@ -174,13 +182,13 @@ static Object getBindingValue(ExportResolution binding) {
174182 return targetEnv .getValue (slot );
175183 }
176184
185+ @ TruffleBoundary
177186 @ Override
178187 public boolean hasProperty (JSDynamicObject thisObj , Object key ) {
179188 if (!Strings .isTString (key )) {
180189 return super .hasProperty (thisObj , key );
181190 }
182- Map <TruffleString , ExportResolution > exports = getExports (thisObj );
183- return Boundaries .mapContainsKey (exports , (TruffleString ) key );
191+ return getExports (thisObj ).containsKey ((TruffleString ) key );
184192 }
185193
186194 @ Override
@@ -189,8 +197,7 @@ public boolean hasOwnProperty(JSDynamicObject thisObj, Object key) {
189197 if (!Strings .isTString (key )) {
190198 return super .hasOwnProperty (thisObj , key );
191199 }
192- Map <TruffleString , ExportResolution > exports = getExports (thisObj );
193- ExportResolution binding = exports .get (key );
200+ ExportResolution binding = getExports (thisObj ).get ((TruffleString ) key );
194201 if (binding != null ) {
195202 // checks for uninitialized bindings
196203 getBindingValue (binding );
@@ -205,12 +212,13 @@ public boolean delete(JSDynamicObject thisObj, long index, boolean isStrict) {
205212 return true ;
206213 }
207214
215+ @ TruffleBoundary
208216 @ Override
209217 public boolean delete (JSDynamicObject thisObj , Object key , boolean isStrict ) {
210218 if (!Strings .isTString (key )) {
211219 return super .delete (thisObj , key , isStrict );
212220 }
213- if (Boundaries . mapContainsKey ( getExports (thisObj ), (TruffleString ) key )) {
221+ if (getExports (thisObj ). containsKey ( (TruffleString ) key )) {
214222 if (isStrict ) {
215223 throw Errors .createTypeErrorNotConfigurableProperty (key );
216224 } else {
@@ -226,6 +234,7 @@ public boolean setPrototypeOf(JSDynamicObject thisObj, JSDynamicObject newProtot
226234 return newPrototype == Null .instance ;
227235 }
228236
237+ @ TruffleBoundary
229238 @ Override
230239 public boolean defineOwnProperty (JSDynamicObject thisObj , Object key , PropertyDescriptor desc , boolean doThrow ) {
231240 if (!Strings .isTString (key )) {
@@ -245,8 +254,7 @@ public PropertyDescriptor getOwnProperty(JSDynamicObject thisObj, Object key) {
245254 if (!Strings .isTString (key )) {
246255 return super .getOwnProperty (thisObj , key );
247256 }
248- Map <TruffleString , ExportResolution > exports = getExports (thisObj );
249- ExportResolution binding = exports .get (key );
257+ ExportResolution binding = getExports (thisObj ).get ((TruffleString ) key );
250258 if (binding != null ) {
251259 Object value = getBindingValue (binding );
252260 return PropertyDescriptor .createData (value , true , true , false );
@@ -266,10 +274,12 @@ public List<Object> getOwnPropertyKeys(JSDynamicObject thisObj, boolean strings,
266274 if (!strings ) {
267275 return symbolKeys ;
268276 }
269- Map <TruffleString , ExportResolution > exports = getExports (thisObj );
277+ UnmodifiableEconomicMap <TruffleString , ExportResolution > exports = getExports (thisObj );
270278 List <Object > keys = new ArrayList <>(exports .size () + symbolKeys .size ());
271279 // TODO: convert these keys earlier
272- keys .addAll (exports .keySet ());
280+ for (TruffleString k : exports .getKeys ()) {
281+ keys .add (k );
282+ }
273283 keys .addAll (symbolKeys );
274284 return keys ;
275285 }
@@ -282,21 +292,25 @@ private static List<Object> symbolKeys(JSDynamicObject thisObj) {
282292 @ Override
283293 @ TruffleBoundary
284294 public boolean setIntegrityLevel (JSDynamicObject obj , boolean freeze , boolean doThrow ) {
285- if (freeze ) {
286- Map <TruffleString , ExportResolution > exports = getExports (obj );
287- if (!exports .isEmpty ()) {
288- ExportResolution firstBinding = exports .values ().iterator ().next ();
289- // Throw ReferenceError if the first binding is uninitialized,
290- // throw TypeError otherwise
291- // checks for an uninitialized binding
292- getBindingValue (firstBinding );
295+ for (ExportResolution binding : getExports (obj ).getValues ()) {
296+ // Check for uninitialized binding (throws ReferenceError)
297+ getBindingValue (binding );
298+ if (freeze ) {
299+ // ReferenceError if the first binding is uninitialized, TypeError otherwise
293300 throw Errors .createTypeError ("not allowed to freeze a namespace object" );
294301 }
295- } else {
296- // Check for uninitialized bindings
297- for (ExportResolution binding : getExports (obj ).values ()) {
298- // can throw ReferenceError
299- getBindingValue (binding );
302+ }
303+ return true ;
304+ }
305+
306+ @ TruffleBoundary
307+ @ Override
308+ public boolean testIntegrityLevel (JSDynamicObject obj , boolean frozen ) {
309+ for (ExportResolution binding : getExports (obj ).getValues ()) {
310+ // Check for uninitialized binding (throws ReferenceError)
311+ getBindingValue (binding );
312+ if (frozen ) {
313+ return false ;
300314 }
301315 }
302316 return true ;
0 commit comments