Fix module reflection when instrumentation is active (#1464)

This commit is contained in:
Jen Basch
2026-03-23 07:42:40 -07:00
committed by GitHub
parent 3f3271d3b1
commit a6db476c70
3 changed files with 24 additions and 4 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,11 +18,13 @@ package org.pkl.core.runtime;
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.instrumentation.InstrumentableNode.WrapperNode;
import org.graalvm.collections.EconomicMap;
import org.graalvm.collections.UnmodifiableEconomicMap;
import org.pkl.core.Composite;
import org.pkl.core.PModule;
import org.pkl.core.PObject;
import org.pkl.core.ast.ExpressionNode;
import org.pkl.core.ast.expression.unary.ImportNode;
import org.pkl.core.ast.member.ObjectMember;
import org.pkl.core.util.EconomicMaps;
@@ -103,9 +105,11 @@ public final class VmTyped extends VmObject {
if (member.isImport()) {
var memberNode = member.getMemberNode();
assert memberNode != null; // import is never a constant
builder.add(
member.getName().toString(),
((ImportNode) memberNode.getBodyNode()).getImportUri().toString());
var bodyNode = memberNode.getBodyNode();
if (bodyNode instanceof WrapperNode wrapper) {
bodyNode = (ExpressionNode) wrapper.getDelegateNode();
}
builder.add(member.getName().toString(), ((ImportNode) bodyNode).getImportUri().toString());
}
}
return builder.build();

View File

@@ -0,0 +1,15 @@
import "pkl:reflect"
import "pkl:test"
class Foo {
bar: String(startsWith("a"))
}
// regression test for VmTyped.getImports()
// which walks module members that are imports and casts their bodies to ImportNode
// the catch activates instrumentation by failing a constraint check
// so that the reflected import member bodies are wrapper nodes instead of ImportNode directly
// the fix for this unwraps the wrapper before casting to ImportNode
foo =
let (_ = test.catchOrNull(() -> new Foo { bar = "baz" }.bar))
reflect.Module(module).imports

View File

@@ -0,0 +1 @@
foo = Map("reflect", "pkl:reflect", "test", "pkl:test")