@@ -10,11 +10,9 @@ namespace Microsoft.JavaScript.NodeApi;
10
10
{
11
11
private readonly JSValue _value ;
12
12
13
- //TODO: [vmoroz] This is a bug. we must never use static variables for JSReference or JSValue
14
- private static readonly Lazy < JSReference > s_iteratorSymbol =
15
- new ( ( ) => new JSReference ( JSValue . Global [ "Symbol" ] [ "iterator" ] ) ) ;
16
- private static readonly Lazy < JSReference > s_asyncIteratorSymbol =
17
- new ( ( ) => new JSReference ( JSValue . Global [ "Symbol" ] [ "asyncIterator" ] ) ) ;
13
+ // Cached symbol references are thread-local because they must be initialized on each JS thread.
14
+ [ ThreadStatic ] private static JSReference ? s_iteratorSymbol ;
15
+ [ ThreadStatic ] private static JSReference ? s_asyncIteratorSymbol ;
18
16
19
17
/// <summary>
20
18
/// Implicitly converts a <see cref="JSSymbol" /> to a <see cref="JSValue" />.
@@ -143,14 +141,45 @@ public string? Description
143
141
}
144
142
}
145
143
144
+ /// <summary>
145
+ /// Gets or creates a symbol with the specified name in the global symbol registry.
146
+ /// </summary>
146
147
public static JSSymbol For ( string name )
147
148
{
148
149
return new JSSymbol ( JSValue . SymbolFor ( name ) ) ;
149
150
}
150
151
151
- public static JSSymbol Iterator => ( JSSymbol ) s_iteratorSymbol . Value . GetValue ( ) ! ;
152
+ /// <summary>
153
+ /// Gets a well-known symbol by its name.
154
+ /// </summary>
155
+ public static JSSymbol Get ( string name )
156
+ {
157
+ return ( JSSymbol ) JSValue . Global [ "Symbol" ] [ name ] ;
158
+ }
159
+
160
+ private static JSSymbol Get ( string name , ref JSReference ? symbolReference )
161
+ {
162
+ if ( symbolReference == null )
163
+ {
164
+ JSSymbol symbol = Get ( name ) ;
165
+ symbolReference = new JSReference ( symbol ) ;
166
+ return symbol ;
167
+ }
168
+ else
169
+ {
170
+ return ( JSSymbol ) symbolReference . GetValue ( ) ;
171
+ }
172
+ }
173
+
174
+ /// <summary>
175
+ /// Gets the well-known symbol for the default iterator.
176
+ /// </summary>
177
+ public static JSSymbol Iterator => Get ( "iterator" , ref s_iteratorSymbol ) ;
152
178
153
- public static JSSymbol AsyncIterator => ( JSSymbol ) s_asyncIteratorSymbol . Value . GetValue ( ) ! ;
179
+ /// <summary>
180
+ /// Gets the well-known symbol for the async iterator.
181
+ /// </summary>
182
+ public static JSSymbol AsyncIterator => Get ( "asyncIterator" , ref s_asyncIteratorSymbol ) ;
154
183
155
184
// TODO: Add static properties for other well-known symbols.
156
185
0 commit comments