Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions docs/unified-bytecode-expansion-contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ must still obey the no-mixed-execution rule.
| `ArrowLexicalThisDependency` | Activation descriptor gate for arrow lexical `this` / `new.target` ownership before ordinary sync routing | Existing arrow invocation route | Arrow route lane | `rtk dotnet test tests/Asynkron.JsEngine.Tests --filter "FullyQualifiedName~UnifiedBytecodeProductionEligibilityTests&FullyQualifiedName~Evaluate_OrdinarySyncActivationDescriptorBlockers_DeclineBeforeCompile"` |
| `ClassConstructorActivation` | Activation descriptor gate for class constructor activation outside the admitted simple base constructor route and explicit derived-constructor `super(...)` route with post-super `this` body reads/writes | Constructor route | Constructor boundary lane | `rtk dotnet test tests/Asynkron.JsEngine.Tests --filter "FullyQualifiedName~UnifiedBytecodeProductionConstructCallTests&FullyQualifiedName~Constructor"` |
| `CallDependency` | Direct eval outside the one-argument non-spread eval-identifier boundary, out-of-boundary call-target preparation, complex call arguments excluding admitted simple/binary template-literal substitutions, simple/binary computed object keys, and zero-argument activation-resolved identifier-call computed object keys, and descriptor-level non-parameter callee calls | Existing sync IR call route | Wider call invocation lane | `rtk dotnet test tests/Asynkron.JsEngine.Tests --filter "FullyQualifiedName~UnifiedBytecodeProductionEligibilityTests&FullyQualifiedName~Evaluate_ActivationDependencies_DeclineBeforeCompile"` |
| `DynamicLookupDependency` | Unresolved identifier loads/stores/typeof/update outside the with-backed dynamic-name path | Existing sync IR / environment lookup route | Dynamic-name lane | `rtk dotnet test tests/Asynkron.JsEngine.Tests --filter "FullyQualifiedName~UnifiedBytecodeProductionEligibilityTests&FullyQualifiedName~Evaluate_DynamicIdentifierLookup_DeclinesWithDynamicLookupDependency"` |
| `DynamicLookupDependency` | Unresolved identifier loads/stores/update outside the admitted ordinary and with-backed dynamic-name paths | Existing sync IR / environment lookup route | Dynamic-name lane | `rtk dotnet test tests/Asynkron.JsEngine.Tests --filter "FullyQualifiedName~UnifiedBytecodeProductionEligibilityTests&FullyQualifiedName~Evaluate_DynamicIdentifierLookup_DeclinesWithDynamicLookupDependency"` |
| `PropertyReadBoundaryOutOfScope` | Named/computed property reads outside the admitted activation-resolved boundaries | Existing sync IR property route | Property read widening lane | `rtk dotnet test tests/Asynkron.JsEngine.Tests --filter "FullyQualifiedName~UnifiedBytecodeProductionEligibilityTests&FullyQualifiedName~Evaluate_ComputedPropertyReadOutsideFirstBoundary_DeclinesWithBoundaryCode"` |
| `PropertyWriteDependency` | Property writes and compound/logical property writes outside the admitted direct property-write shapes, supported computed expression-key mutation shapes, simple nested named receiver assignment shape, nested named compound-write shape, and nested named logical-write shape | Existing sync IR property-write route | Property write widening lane | `rtk dotnet test tests/Asynkron.JsEngine.Tests --filter "FullyQualifiedName~UnifiedBytecodeProductionEligibilityTests&FullyQualifiedName~Evaluate_LogicalAndAssignment_UnsupportedShapes_DeclineWithExplicitCodes"` |
| `PropertyUpdateDependency` | Property and identifier update expressions outside the admitted direct update, computed expression-key update, and simple nested named receiver update boundary | Existing sync IR update route | Property update lane | `rtk dotnet test tests/Asynkron.JsEngine.Tests --filter "FullyQualifiedName~UnifiedBytecodeProductionEligibilityTests&FullyQualifiedName~Evaluate_NestedNamedPropertyUpdate_AcceptsOwnedPropertyOpcodes"` |
Expand Down Expand Up @@ -837,10 +837,11 @@ support today.
or descriptor-backed assignment lanes remain outside the admitted boundary
(`DestructuringDependency`).
6. Dynamic lookup families remain outside the admitted boundary
(`DynamicLookupDependency`) except for the explicit with-backed dynamic name
slice above. Direct eval outside the admitted one-argument non-spread
eval-identifier boundary, unresolved non-with lookup shapes, and captured
dynamic activation still decline before VM execution.
(`DynamicLookupDependency`) except for the ordinary dynamic-name environment
path and the explicit with-backed dynamic name slice above. Direct eval
outside the admitted one-argument non-spread eval-identifier boundary,
unresolved dynamic activation, and unsupported unresolved lookup shapes still
decline before VM execution.
7. Label-dependent control flow is now admitted (ADR 0285): labeled statements,
labeled loops, labeled block `break`, and labeled `break`/`continue` route
through the compiler-owned resolved-target path. The remaining
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4338,7 +4338,7 @@ function kind(value) {
}

[Fact]
public void Evaluate_TypeOfUnresolvedIdentifier_DeclinesWithDynamicLookupDependency()
public void Evaluate_TypeOfUnresolvedIdentifier_AcceptsOrdinaryDynamicNameOpcode()
{
var plan = GetFunctionPlan("""
function kind() {
Expand All @@ -4349,11 +4349,13 @@ function kind() {

var result = UnifiedBytecodeProductionEligibility.Evaluate(
plan,
new UnifiedBytecodeProductionActivationDescriptor());
new UnifiedBytecodeProductionActivationDescriptor(
AllowsOrdinaryDynamicIdentifierEnvironmentOperations: true));

Assert.False(result.IsEligible);
Assert.Equal(UnifiedBytecodeProductionDeclineCode.DynamicLookupDependency, result.Code);
Assert.Contains("typeof identifier 'missing'", result.Reason, StringComparison.Ordinal);
Assert.True(result.IsEligible, result.Reason);
Assert.Equal(UnifiedBytecodeProductionDeclineCode.None, result.Code);
Assert.Contains(result.Program.Instructions, instruction =>
instruction.OpCode == UnifiedBytecodeOpCode.TypeOfDynamicIdentifier);
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3144,6 +3144,25 @@ static record => record.Message.Contains(
StringComparison.Ordinal));
}

[Fact(Timeout = 5000)]
public async Task TypeOfUnresolvedIdentifier_UsesUnifiedBytecodeProductionFastPath()
{
await using var engine = CreateEngine();
var result = await engine.Evaluate("""
function kind() {
return typeof missing;
}

kind();
""");

Assert.Equal("undefined", result?.ToString());
Assert.Contains(CurrentLogger!.Collector.Snapshot(),
static record => record.Message.Contains(
"unified-bytecode-production-fast-path func=kind argc=0",
StringComparison.Ordinal));
}

[Fact(Timeout = 5000)]
public async Task TypeOfIdentifierForLexicalTdz_PropagatesReferenceErrorThroughUnifiedBytecodeProductionFastPath()
{
Expand Down