@@ -354,7 +354,54 @@ a scope out of sync with the lexical scoping, an alternative proposal is to
354
354
specialize the handling of async context variables in ` using ` declarations as
355
355
follows:
356
356
357
- // TODO: snek
357
+ ``` js
358
+ class AsyncVariableScope {
359
+ #asyncVar;
360
+ #value;
361
+ #previousContextMapping;
362
+
363
+ constructor (asyncVar , value ) {
364
+ this .#asyncVar = asyncVar;
365
+ this .#value = value;
366
+ }
367
+
368
+ // if present, slot called by `using` instead of @@enter
369
+ [[UsingEnter]]() {
370
+ const asyncContextMapping = snapshot + { [[AsyncContextKey]]: this .[[AsyncVariable]], [[AsyncContextValue]]: this .[[Value]] };
371
+ this .#previousContextMapping = AsyncContextSwap (asyncContextMapping);
372
+ }
373
+
374
+ // if present, slot called by `using` instead of @@dispose
375
+ [[UsingDispose]]() {
376
+ AsyncContextSwap (this .#previousContextMapping);
377
+ }
378
+ }
379
+ ```
380
+
381
+ This can then be used in user code with subclassing:
382
+
383
+ ``` js
384
+ class SpanRef extends AsyncVariableScopable {
385
+ #span;
386
+
387
+ constructor (tracer , span ) {
388
+ super (tracer .asyncContext , span);
389
+ this .#span = span;
390
+ }
391
+
392
+ // span apis here, etc...
393
+ setAttribute (name , value ) { this .#span .setAttribute (name, value); }
394
+ }
395
+
396
+ class Tracer {
397
+ startSpan () {
398
+ const span = this .createSpan ();
399
+ return new SpanRef (this , span);
400
+ }
401
+ }
402
+
403
+ using span = tracer .startSpan ();
404
+ ```
358
405
359
406
# Use cases
360
407
0 commit comments