From 4f61b4ca6d9c075a514049676ca59deaceb73eaa Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Wed, 24 Apr 2024 19:06:38 +0200 Subject: [PATCH 1/7] [GR-52930] Added TruffleLanguage.Env::getScope(LanguageInfo). --- truffle/CHANGELOG.md | 2 + .../api/test/polyglot/LanguageSPITest.java | 192 ++++++++++++++++++ .../oracle/truffle/api/TruffleLanguage.java | 24 +++ .../com/oracle/truffle/api/impl/Accessor.java | 2 + .../truffle/polyglot/EngineAccessor.java | 9 + 5 files changed, 229 insertions(+) diff --git a/truffle/CHANGELOG.md b/truffle/CHANGELOG.md index ec8940c38180..12c5336e98d3 100644 --- a/truffle/CHANGELOG.md +++ b/truffle/CHANGELOG.md @@ -12,6 +12,8 @@ This changelog summarizes major changes between Truffle versions relevant to lan * GR-38322 Added `--engine.TraceMissingSafepointPollInterval=N` to show Java stacktraces when there are [missing `TruffleSafepoint.poll()` calls](https://github.com/oracle/graal/blob/master/truffle/docs/Safepoints.md#find-missing-safepoint-polls). * GR-52644 Deprecated `TruffleLanguage.Registration.needsAllEncodings`, no longer needs to be declared. It is sufficient for a language module to require `org.graalvm.shadowed.jcodings` to enable all string encodings. * GR-51172 Add `CompilerDirectives.ensureAllocatedHere` to mark an allocation as non-movable. This allows language developers to mark special allocations as non-optimizable to allow better control for allocations potentially throwing OutOfMemoryErrors. +* GR-52930 Added `TruffleLanguage.Env.getHostLanguage()` returning the host language info. +* GR-52930 Added `TruffleLanguage.Env.getScope(LanguageInfo)` returning the top scope object of the language. ## Version 24.0.0 diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageSPITest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageSPITest.java index e2b288a7d138..93671f8ec5ba 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageSPITest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageSPITest.java @@ -3335,6 +3335,198 @@ public void testInitializeFromServiceNonInternalLanguage() { } } + @TruffleLanguage.Registration + public static final class TestGetScopeInternalLanguage extends AbstractExecutableTestLanguage { + + @Override + @TruffleBoundary + protected Object execute(RootNode node, Env env, Object[] contextArguments, Object[] frameArguments) throws Exception { + Object internalLanguageScope = env.getScope(env.getInternalLanguages().get(GetScopeTargetInternalLanguage.ID)); + assertTrue(interop.isScope(internalLanguageScope)); + assertTrue(interop.hasMembers(internalLanguageScope)); + return null; + } + } + + @Test + public void testGetScopeInternalLanguage() { + try (Context context = Context.newBuilder().build()) { + AbstractExecutableTestLanguage.parseTestLanguage(context, TestGetScopeInternalLanguage.class, "").execute(); + } + } + + @TruffleLanguage.Registration(dependentLanguages = GetScopeTargetNonInternalLanguage.ID) + public static final class TestGetScopeDependentLanguage extends AbstractExecutableTestLanguage { + + @Override + @TruffleBoundary + protected Object execute(RootNode node, Env env, Object[] contextArguments, Object[] frameArguments) throws Exception { + Object internalLanguageScope = env.getScope(env.getInternalLanguages().get(GetScopeTargetNonInternalLanguage.ID)); + assertTrue(interop.isScope(internalLanguageScope)); + assertTrue(interop.hasMembers(internalLanguageScope)); + return null; + } + } + + @Test + public void testGetScopeDependentLanguage() { + try (Context context = Context.newBuilder().build()) { + AbstractExecutableTestLanguage.parseTestLanguage(context, TestGetScopeDependentLanguage.class, "").execute(); + } + } + + @TruffleLanguage.Registration + public static final class TestGetScopeAllowedLanguage extends AbstractExecutableTestLanguage { + + @Override + @TruffleBoundary + protected Object execute(RootNode node, Env env, Object[] contextArguments, Object[] frameArguments) throws Exception { + Object internalLanguageScope = env.getScope(env.getInternalLanguages().get(GetScopeTargetNonInternalLanguage.ID)); + assertTrue(interop.isScope(internalLanguageScope)); + assertTrue(interop.hasMembers(internalLanguageScope)); + return null; + } + } + + @Test + public void testGetScopeAllowedLanguage() { + try (Context context = Context.newBuilder().allowPolyglotAccess(PolyglotAccess.ALL).build()) { + AbstractExecutableTestLanguage.parseTestLanguage(context, TestGetScopeAllowedLanguage.class, "").execute(); + } + PolyglotAccess polyglotAccess = PolyglotAccess.newBuilder().allowEval(TestUtils.getDefaultLanguageId(TestGetScopeAllowedLanguage.class), GetScopeTargetNonInternalLanguage.ID).build(); + try (Context context = Context.newBuilder().allowPolyglotAccess(polyglotAccess).build()) { + AbstractExecutableTestLanguage.parseTestLanguage(context, TestGetScopeAllowedLanguage.class, "").execute(); + } + } + + @TruffleLanguage.Registration + public static final class TestGetScopeDeniedLanguage extends AbstractExecutableTestLanguage { + + @Override + @TruffleBoundary + protected Object execute(RootNode node, Env env, Object[] contextArguments, Object[] frameArguments) throws Exception { + assertNull(env.getInternalLanguages().get(GetScopeTargetNonInternalLanguage.ID)); + assertNull(env.getPublicLanguages().get(GetScopeTargetNonInternalLanguage.ID)); + return null; + } + } + + @Test + public void testGetScopeDeniedLanguage() { + try (Context context = Context.newBuilder().build()) { + AbstractExecutableTestLanguage.parseTestLanguage(context, TestGetScopeDeniedLanguage.class, "").execute(); + } + } + + static class GetScopeTargetLanguage extends TruffleLanguage { + + @Override + protected LanguageContext createContext(Env env) { + return new LanguageContext(getClass()); + } + + @Override + protected void initializeContext(LanguageContext context) throws Exception { + context.initialized = true; + } + + @Override + protected Object getScope(LanguageContext context) { + assertTrue(context.initialized); + return context.scope; + } + + static final class LanguageContext { + + final Object scope; + volatile boolean initialized; + + LanguageContext(Class> languageClass) { + scope = new Scope(languageClass); + } + + @ExportLibrary(InteropLibrary.class) + record Scope(Class> language) implements TruffleObject { + + @ExportMessage + @SuppressWarnings("static-method") + boolean hasMembers() { + return true; + } + + @ExportMessage + @SuppressWarnings({"static-method", "unused"}) + Object getMembers(boolean includeInternal) { + return new ScopeKeys(new String[0]); + } + + @ExportMessage + @SuppressWarnings("static-method") + boolean isScope() { + return true; + } + + @ExportMessage + @SuppressWarnings("static-method") + boolean hasLanguage() { + return true; + } + + @ExportMessage + Class> getLanguage() { + return language; + } + + @ExportMessage + @TruffleBoundary + @SuppressWarnings("unused") + Object toDisplayString(boolean allowSideEffects) { + return String.format("%s Scope", language.getSimpleName()); + } + } + + @ExportLibrary(InteropLibrary.class) + record ScopeKeys(String[] keys) implements TruffleObject { + + @SuppressWarnings("static-method") + @ExportMessage + boolean hasArrayElements() { + return true; + } + + @ExportMessage + boolean isArrayElementReadable(long index) { + return index >= 0 && index < keys.length; + } + + @ExportMessage + long getArraySize() { + return keys.length; + } + + @ExportMessage + Object readArrayElement(long index) throws InvalidArrayIndexException { + if (isArrayElementReadable(index)) { + return keys[(int) index]; + } else { + CompilerDirectives.transferToInterpreter(); + throw InvalidArrayIndexException.create(index); + } + } + } + } + } + + @TruffleLanguage.Registration(id = GetScopeTargetInternalLanguage.ID, name = GetScopeTargetInternalLanguage.ID, version = "1.0", contextPolicy = ContextPolicy.SHARED, internal = true, interactive = false) + static final class GetScopeTargetInternalLanguage extends GetScopeTargetLanguage { + static final String ID = "GetScopeTargetInternalLanguage"; + } + + @TruffleLanguage.Registration(id = GetScopeTargetNonInternalLanguage.ID, name = GetScopeTargetNonInternalLanguage.ID, version = "1.0", contextPolicy = ContextPolicy.SHARED, interactive = false) + static final class GetScopeTargetNonInternalLanguage extends GetScopeTargetLanguage { + static final String ID = "GetScopeTargetNonInternalLanguage"; + } + private static void testInitializeFromServiceImpl(Context context, Function languageResolver, Supplier verifier) { ProxyLanguage.setDelegate(new ProxyLanguage() { @Override diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java index 6c0ac747ce82..3340cc504541 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java @@ -3735,6 +3735,30 @@ public SandboxPolicy getSandboxPolicy() { return LanguageAccessor.engineAccess().getContextSandboxPolicy(this.polyglotLanguageContext); } + /** + * Retrieves the top scope object of {@code language}, if available. This method first + * checks if the specified {@code language} is accessible from the current language. If not, + * a {@link IllegalArgumentException} is thrown. If the language is accessible, this method + * initializes the language if it has not been initialized already, and then returns the + * top-level scope object. The returned object is an + * {@link com.oracle.truffle.api.interop.InteropLibrary#isScope(Object) interop scope + * object}, or {@code null} if the language does not support such concept. + * + * @see TruffleLanguage#getScope(Object) + * @since 24.1 + */ + @TruffleBoundary + public Object getScope(LanguageInfo language) { + try { + Env env = LanguageAccessor.engineAccess().getEnvForLanguage(polyglotLanguageContext, language, getSpi().languageInfo); + Object result = env.getSpi().getScope(env.context); + assert result == null || LanguageAccessor.interopAccess().isScopeObject(result) : String.format("%s is not a scope", result); + return result; + } catch (Throwable t) { + throw engineToLanguageException(t); + } + } + /* * For reflective use in tests. */ diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java index 9c721507c6e7..ebc1da60b210 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java @@ -368,6 +368,8 @@ public final void detachOutputConsumer(DispatchOutputStream dos, OutputStream ou public abstract Env getEnvForInstrument(LanguageInfo language); + public abstract Env getEnvForLanguage(Object polyglotLanguageContext, LanguageInfo requiredLanguage, LanguageInfo accessingLanguage); + public abstract boolean hasCurrentContext(); public abstract boolean isDisposed(Object polyglotLanguageContext); diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java index ee945220f603..fd398270cf9c 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java @@ -503,6 +503,15 @@ public TruffleLanguage.Env getEnvForInstrument(LanguageInfo info) { return context.getContextInitialized(language, null).env; } + @Override + public TruffleLanguage.Env getEnvForLanguage(Object polyglotLanguageContext, LanguageInfo requiredLanguage, LanguageInfo accessingLanguage) { + PolyglotContextImpl context = ((PolyglotLanguageContext) polyglotLanguageContext).context; + PolyglotLanguage requiredPolyglotLanguage = context.engine.findLanguage(requiredLanguage); + PolyglotLanguage accessingPolyglotLanguage = context.engine.findLanguage(accessingLanguage); + PolyglotLanguageContext requestedPolyglotLanguageContext = context.getContextInitialized(requiredPolyglotLanguage, accessingPolyglotLanguage); + return requestedPolyglotLanguageContext.env; + } + static PolyglotLanguage findObjectLanguage(PolyglotEngineImpl engine, Object value) { InteropLibrary lib = InteropLibrary.getFactory().getUncached(value); if (lib.hasLanguage(value)) { From d999c636da58c05565d3358b9fa67325f70705b3 Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Wed, 29 May 2024 13:46:19 +0200 Subject: [PATCH 2/7] Allow languages to access scopes of other languages. --- truffle/CHANGELOG.md | 1 + .../polyglot/ContextPolyglotAccessTest.java | 18 +++- .../oracle/truffle/api/TruffleLanguage.java | 90 ++++++++++++++++--- .../com/oracle/truffle/api/impl/Accessor.java | 2 +- .../truffle/polyglot/EngineAccessor.java | 14 +-- 5 files changed, 105 insertions(+), 20 deletions(-) diff --git a/truffle/CHANGELOG.md b/truffle/CHANGELOG.md index 12c5336e98d3..1bd10c6ae529 100644 --- a/truffle/CHANGELOG.md +++ b/truffle/CHANGELOG.md @@ -14,6 +14,7 @@ This changelog summarizes major changes between Truffle versions relevant to lan * GR-51172 Add `CompilerDirectives.ensureAllocatedHere` to mark an allocation as non-movable. This allows language developers to mark special allocations as non-optimizable to allow better control for allocations potentially throwing OutOfMemoryErrors. * GR-52930 Added `TruffleLanguage.Env.getHostLanguage()` returning the host language info. * GR-52930 Added `TruffleLanguage.Env.getScope(LanguageInfo)` returning the top scope object of the language. +* GR-28866 Added `TruffleLanguage.Env.getScopePublic(LanguageInfo)` and `TruffleLanguage.Env.getScopeInternal(LanguageInfo)` to allow languages direct access to other language scopes to implement new polyglot builtins. ## Version 24.0.0 diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPolyglotAccessTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPolyglotAccessTest.java index 0b570716e886..7594dbcdde57 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPolyglotAccessTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPolyglotAccessTest.java @@ -44,6 +44,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -1068,10 +1069,16 @@ private static void assertInternalEvalDenied(Env env, String targetId) { private static void assertInternalEvalAllowed(Env env, String targetId) { assertTrue(env.getInternalLanguages().containsKey(targetId)); assertNotNull(env.parseInternal(Source.newBuilder(targetId, "", "").build())); + assertNotNull(env.getScopeInternal(env.getInternalLanguages().get(targetId))); } private static void assertPublicEvalDenied(Env env, String targetId) { - assertFalse(env.getPublicLanguages().containsKey(targetId)); + LanguageInfo info = env.getPublicLanguages().get(targetId); + assertNull(info); + LanguageInfo internalLanguage = env.getInternalLanguages().get(targetId); + if (internalLanguage != null) { + assertFails(() -> env.getScopePublic(internalLanguage), SecurityException.class); + } try { env.parsePublic(Source.newBuilder(targetId, "", "").build()); fail(); @@ -1082,11 +1089,13 @@ private static void assertPublicEvalDenied(Env env, String targetId) { } private static void assertPublicEvalAllowed(Env env, String targetId) { - assertTrue(env.getPublicLanguages().containsKey(targetId)); + LanguageInfo info = env.getPublicLanguages().get(targetId); + assertNotNull(info); assertNotNull(env.parsePublic(Source.newBuilder(targetId, "", "").build())); if (env.getPublicLanguages().size() > 1) { assertTrue(env.isPolyglotEvalAllowed()); } + assertNotNull(env.getScopePublic(info)); } @Registration(id = LANGUAGE1, name = LANGUAGE1, dependentLanguages = DEPENDENT) @@ -1102,6 +1111,11 @@ protected CallTarget parse(ParsingRequest request) throws Exception { return RootNode.createConstantNode(true).getCallTarget(); } + @Override + protected Object getScope(Env context) { + return new RetainedSizeContextBoundaryTest.ScopeObject(); + } + public static Env getContext(String language) { ContextReference ref; switch (language) { diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java index 3340cc504541..d689b9cf588b 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java @@ -3736,24 +3736,90 @@ public SandboxPolicy getSandboxPolicy() { } /** - * Retrieves the top scope object of {@code language}, if available. This method first - * checks if the specified {@code language} is accessible from the current language. If not, - * a {@link IllegalArgumentException} is thrown. If the language is accessible, this method - * initializes the language if it has not been initialized already, and then returns the - * top-level scope object. The returned object is an + * Returns the scope object of a non-null {@link #getPublicLanguages() public language}. The + * returned value follows the contract of {@link TruffleLanguage#getScope(Object)} of the + * other language, therefore it must be an * {@link com.oracle.truffle.api.interop.InteropLibrary#isScope(Object) interop scope - * object}, or {@code null} if the language does not support such concept. + * object} and may have + * {@link com.oracle.truffle.api.interop.InteropLibrary#hasScopeParent(Object) parent + * scopes}. The bindings object exposes all top scopes variables as flattened + * {@link com.oracle.truffle.api.interop.InteropLibrary#getMembers(Object) members}. In + * addition to being a scope the returned object may implement any number of the + * {@link com.oracle.truffle.api.interop.InteropLibrary interop traits}. The interop members + * of the returned object are typically writable, but that is not guaranteed. + *

+ * The suffix public in the method name indicates that the result of this + * method is safe to be exposed by default to guest applications. For example, languages + * should use this method to implement the semantics of their polyglot bindings builtin, but + * is not limited to that. + *

+ * All {@link #getPublicLanguages() public} languages with + * {@link #isPolyglotEvalAllowed(LanguageInfo) eval permissions} are accessible. If a + * language is not accessible then an {@link SecurityException} is thrown. The scope of the + * current language is always accessible, but it is recommended to use a language specific + * way to access symbols of the current language. + *

+ * Languages should check for {@link #isPolyglotEvalAllowed(LanguageInfo) eval permissions} + * for each {@link #getPublicLanguages() public language} prior to calling this method, + * otherwise it might cause an internal error if not sufficient privileges are available. + * + * @return the scope, or null if the requested language does not support such a + * concept + * @throws IllegalStateException if polyglot context associated with this environment is not + * entered + * @throws SecurityException if polyglot scope access is not enabled for this language. + * @see #getScopeInternal(LanguageInfo) + * @see #isPolyglotEvalAllowed(LanguageInfo) + * @see #getPolyglotBindings() * - * @see TruffleLanguage#getScope(Object) * @since 24.1 */ @TruffleBoundary - public Object getScope(LanguageInfo language) { + public Object getScopePublic(LanguageInfo language) throws IllegalArgumentException { + Objects.requireNonNull(language); + checkDisposed(); + try { + return LanguageAccessor.engineAccess().getScope(polyglotLanguageContext, language, false); + } catch (Throwable t) { + throw engineToLanguageException(t); + } + } + + /** + * Returns the scope object of a non-null {@link #getInternalLanguages() internal language}. + * Works the same as {@link #getScopePublic(LanguageInfo)} but it also returns scopes of + * internal and dependent languages. + *

+ * The suffix internal in the method name indicates that the result of this + * method is not safe to be exposed to arbitrary guest code, by default. Use + * {@link #getScopePublic(LanguageInfo)} for that purpose instead. For example, this method + * could be used to access a fixed set of symbols from the Truffle Native Interface, e.g. to + * load native language extensions. Languages may decide to expose scopes of internal + * languages to arbitrary guest code for testing purposes. Make sure this option is disabled + * by default and enabled using an {@link OptionCategory#INTERNAL internal} option only. + *

+ * The scope of the current language is always accessible, but it is recommended to use a + * language specific way to access symbols of the current language. + *

+ * It is recommended to only use this method for {@link LanguageInfo#isInternal() internal} + * or {@link TruffleLanguage.Registration#dependentLanguages() dependent languages}. For + * convenience, this method will also succeed for all accessible + * {@link #getPublicLanguages() public languages} with + * {@link #isPolyglotEvalAllowed(LanguageInfo) eval permissions}. + * + * @see #getScopePublic(LanguageInfo) + * @return the scope, or null if the requested language does not support such a + * concept + * @throws IllegalStateException if polyglot context associated with this environment is not + * entered + * @throws SecurityException if polyglot scope access is not enabled for this language. + * @since 24.1 + */ + @TruffleBoundary + public Object getScopeInternal(LanguageInfo language) { + checkDisposed(); try { - Env env = LanguageAccessor.engineAccess().getEnvForLanguage(polyglotLanguageContext, language, getSpi().languageInfo); - Object result = env.getSpi().getScope(env.context); - assert result == null || LanguageAccessor.interopAccess().isScopeObject(result) : String.format("%s is not a scope", result); - return result; + return LanguageAccessor.engineAccess().getScope(polyglotLanguageContext, language, true); } catch (Throwable t) { throw engineToLanguageException(t); } diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java index ebc1da60b210..9f946a6690cb 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java @@ -368,7 +368,7 @@ public final void detachOutputConsumer(DispatchOutputStream dos, OutputStream ou public abstract Env getEnvForInstrument(LanguageInfo language); - public abstract Env getEnvForLanguage(Object polyglotLanguageContext, LanguageInfo requiredLanguage, LanguageInfo accessingLanguage); + public abstract Object getScope(Object polyglotLanguageContext, LanguageInfo languageInfo, boolean internal); public abstract boolean hasCurrentContext(); diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java index fd398270cf9c..d50af6f93046 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java @@ -504,12 +504,16 @@ public TruffleLanguage.Env getEnvForInstrument(LanguageInfo info) { } @Override - public TruffleLanguage.Env getEnvForLanguage(Object polyglotLanguageContext, LanguageInfo requiredLanguage, LanguageInfo accessingLanguage) { - PolyglotContextImpl context = ((PolyglotLanguageContext) polyglotLanguageContext).context; + public Object getScope(Object polyglotLanguageContext, LanguageInfo requiredLanguage, boolean internal) { + PolyglotLanguageContext languageContext = (PolyglotLanguageContext) polyglotLanguageContext; + PolyglotContextImpl context = languageContext.context; + if ((internal && !getInternalLanguages(languageContext).containsKey(requiredLanguage.getId())) || // + (!internal && !getPublicLanguages(languageContext).containsKey(requiredLanguage.getId()))) { + throw new SecurityException(String.format("Access to language '%s' is not permitted.", requiredLanguage.getId())); + } PolyglotLanguage requiredPolyglotLanguage = context.engine.findLanguage(requiredLanguage); - PolyglotLanguage accessingPolyglotLanguage = context.engine.findLanguage(accessingLanguage); - PolyglotLanguageContext requestedPolyglotLanguageContext = context.getContextInitialized(requiredPolyglotLanguage, accessingPolyglotLanguage); - return requestedPolyglotLanguageContext.env; + PolyglotLanguageContext requestedPolyglotLanguageContext = context.getContextInitialized(requiredPolyglotLanguage, languageContext.language); + return LANGUAGE.getScope(requestedPolyglotLanguageContext.env); } static PolyglotLanguage findObjectLanguage(PolyglotEngineImpl engine, Object value) { From 93c8722850c9e5179508847bd6ddf2386205c8ab Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Wed, 29 May 2024 14:30:07 +0200 Subject: [PATCH 3/7] Post merge fixes. --- .../api/test/polyglot/LanguageSPITest.java | 192 ------------------ .../oracle/truffle/api/TruffleLanguage.java | 8 +- .../truffle/polyglot/EngineAccessor.java | 13 +- 3 files changed, 15 insertions(+), 198 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageSPITest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageSPITest.java index 93671f8ec5ba..e2b288a7d138 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageSPITest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageSPITest.java @@ -3335,198 +3335,6 @@ public void testInitializeFromServiceNonInternalLanguage() { } } - @TruffleLanguage.Registration - public static final class TestGetScopeInternalLanguage extends AbstractExecutableTestLanguage { - - @Override - @TruffleBoundary - protected Object execute(RootNode node, Env env, Object[] contextArguments, Object[] frameArguments) throws Exception { - Object internalLanguageScope = env.getScope(env.getInternalLanguages().get(GetScopeTargetInternalLanguage.ID)); - assertTrue(interop.isScope(internalLanguageScope)); - assertTrue(interop.hasMembers(internalLanguageScope)); - return null; - } - } - - @Test - public void testGetScopeInternalLanguage() { - try (Context context = Context.newBuilder().build()) { - AbstractExecutableTestLanguage.parseTestLanguage(context, TestGetScopeInternalLanguage.class, "").execute(); - } - } - - @TruffleLanguage.Registration(dependentLanguages = GetScopeTargetNonInternalLanguage.ID) - public static final class TestGetScopeDependentLanguage extends AbstractExecutableTestLanguage { - - @Override - @TruffleBoundary - protected Object execute(RootNode node, Env env, Object[] contextArguments, Object[] frameArguments) throws Exception { - Object internalLanguageScope = env.getScope(env.getInternalLanguages().get(GetScopeTargetNonInternalLanguage.ID)); - assertTrue(interop.isScope(internalLanguageScope)); - assertTrue(interop.hasMembers(internalLanguageScope)); - return null; - } - } - - @Test - public void testGetScopeDependentLanguage() { - try (Context context = Context.newBuilder().build()) { - AbstractExecutableTestLanguage.parseTestLanguage(context, TestGetScopeDependentLanguage.class, "").execute(); - } - } - - @TruffleLanguage.Registration - public static final class TestGetScopeAllowedLanguage extends AbstractExecutableTestLanguage { - - @Override - @TruffleBoundary - protected Object execute(RootNode node, Env env, Object[] contextArguments, Object[] frameArguments) throws Exception { - Object internalLanguageScope = env.getScope(env.getInternalLanguages().get(GetScopeTargetNonInternalLanguage.ID)); - assertTrue(interop.isScope(internalLanguageScope)); - assertTrue(interop.hasMembers(internalLanguageScope)); - return null; - } - } - - @Test - public void testGetScopeAllowedLanguage() { - try (Context context = Context.newBuilder().allowPolyglotAccess(PolyglotAccess.ALL).build()) { - AbstractExecutableTestLanguage.parseTestLanguage(context, TestGetScopeAllowedLanguage.class, "").execute(); - } - PolyglotAccess polyglotAccess = PolyglotAccess.newBuilder().allowEval(TestUtils.getDefaultLanguageId(TestGetScopeAllowedLanguage.class), GetScopeTargetNonInternalLanguage.ID).build(); - try (Context context = Context.newBuilder().allowPolyglotAccess(polyglotAccess).build()) { - AbstractExecutableTestLanguage.parseTestLanguage(context, TestGetScopeAllowedLanguage.class, "").execute(); - } - } - - @TruffleLanguage.Registration - public static final class TestGetScopeDeniedLanguage extends AbstractExecutableTestLanguage { - - @Override - @TruffleBoundary - protected Object execute(RootNode node, Env env, Object[] contextArguments, Object[] frameArguments) throws Exception { - assertNull(env.getInternalLanguages().get(GetScopeTargetNonInternalLanguage.ID)); - assertNull(env.getPublicLanguages().get(GetScopeTargetNonInternalLanguage.ID)); - return null; - } - } - - @Test - public void testGetScopeDeniedLanguage() { - try (Context context = Context.newBuilder().build()) { - AbstractExecutableTestLanguage.parseTestLanguage(context, TestGetScopeDeniedLanguage.class, "").execute(); - } - } - - static class GetScopeTargetLanguage extends TruffleLanguage { - - @Override - protected LanguageContext createContext(Env env) { - return new LanguageContext(getClass()); - } - - @Override - protected void initializeContext(LanguageContext context) throws Exception { - context.initialized = true; - } - - @Override - protected Object getScope(LanguageContext context) { - assertTrue(context.initialized); - return context.scope; - } - - static final class LanguageContext { - - final Object scope; - volatile boolean initialized; - - LanguageContext(Class> languageClass) { - scope = new Scope(languageClass); - } - - @ExportLibrary(InteropLibrary.class) - record Scope(Class> language) implements TruffleObject { - - @ExportMessage - @SuppressWarnings("static-method") - boolean hasMembers() { - return true; - } - - @ExportMessage - @SuppressWarnings({"static-method", "unused"}) - Object getMembers(boolean includeInternal) { - return new ScopeKeys(new String[0]); - } - - @ExportMessage - @SuppressWarnings("static-method") - boolean isScope() { - return true; - } - - @ExportMessage - @SuppressWarnings("static-method") - boolean hasLanguage() { - return true; - } - - @ExportMessage - Class> getLanguage() { - return language; - } - - @ExportMessage - @TruffleBoundary - @SuppressWarnings("unused") - Object toDisplayString(boolean allowSideEffects) { - return String.format("%s Scope", language.getSimpleName()); - } - } - - @ExportLibrary(InteropLibrary.class) - record ScopeKeys(String[] keys) implements TruffleObject { - - @SuppressWarnings("static-method") - @ExportMessage - boolean hasArrayElements() { - return true; - } - - @ExportMessage - boolean isArrayElementReadable(long index) { - return index >= 0 && index < keys.length; - } - - @ExportMessage - long getArraySize() { - return keys.length; - } - - @ExportMessage - Object readArrayElement(long index) throws InvalidArrayIndexException { - if (isArrayElementReadable(index)) { - return keys[(int) index]; - } else { - CompilerDirectives.transferToInterpreter(); - throw InvalidArrayIndexException.create(index); - } - } - } - } - } - - @TruffleLanguage.Registration(id = GetScopeTargetInternalLanguage.ID, name = GetScopeTargetInternalLanguage.ID, version = "1.0", contextPolicy = ContextPolicy.SHARED, internal = true, interactive = false) - static final class GetScopeTargetInternalLanguage extends GetScopeTargetLanguage { - static final String ID = "GetScopeTargetInternalLanguage"; - } - - @TruffleLanguage.Registration(id = GetScopeTargetNonInternalLanguage.ID, name = GetScopeTargetNonInternalLanguage.ID, version = "1.0", contextPolicy = ContextPolicy.SHARED, interactive = false) - static final class GetScopeTargetNonInternalLanguage extends GetScopeTargetLanguage { - static final String ID = "GetScopeTargetNonInternalLanguage"; - } - private static void testInitializeFromServiceImpl(Context context, Function languageResolver, Supplier verifier) { ProxyLanguage.setDelegate(new ProxyLanguage() { @Override diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java index d689b9cf588b..439873bceb12 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java @@ -3779,7 +3779,9 @@ public Object getScopePublic(LanguageInfo language) throws IllegalArgumentExcept Objects.requireNonNull(language); checkDisposed(); try { - return LanguageAccessor.engineAccess().getScope(polyglotLanguageContext, language, false); + Object result = LanguageAccessor.engineAccess().getScope(polyglotLanguageContext, language, false); + assert result == null || LanguageAccessor.interopAccess().isScopeObject(result) : String.format("%s is not a scope", result); + return result; } catch (Throwable t) { throw engineToLanguageException(t); } @@ -3819,7 +3821,9 @@ public Object getScopePublic(LanguageInfo language) throws IllegalArgumentExcept public Object getScopeInternal(LanguageInfo language) { checkDisposed(); try { - return LanguageAccessor.engineAccess().getScope(polyglotLanguageContext, language, true); + Object result = LanguageAccessor.engineAccess().getScope(polyglotLanguageContext, language, true); + assert result == null || LanguageAccessor.interopAccess().isScopeObject(result) : String.format("%s is not a scope", result); + return result; } catch (Throwable t) { throw engineToLanguageException(t); } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java index d50af6f93046..df56bdb0649f 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java @@ -506,11 +506,16 @@ public TruffleLanguage.Env getEnvForInstrument(LanguageInfo info) { @Override public Object getScope(Object polyglotLanguageContext, LanguageInfo requiredLanguage, boolean internal) { PolyglotLanguageContext languageContext = (PolyglotLanguageContext) polyglotLanguageContext; - PolyglotContextImpl context = languageContext.context; - if ((internal && !getInternalLanguages(languageContext).containsKey(requiredLanguage.getId())) || // - (!internal && !getPublicLanguages(languageContext).containsKey(requiredLanguage.getId()))) { - throw new SecurityException(String.format("Access to language '%s' is not permitted.", requiredLanguage.getId())); + boolean allowed; + if (internal) { + allowed = getInternalLanguages(languageContext).containsKey(requiredLanguage.getId()); + } else { + allowed = getPublicLanguages(languageContext).containsKey(requiredLanguage.getId()); } + if (!allowed) { + throw new PolyglotEngineException(new SecurityException(String.format("Access to language '%s' is not permitted.", requiredLanguage.getId()))); + } + PolyglotContextImpl context = languageContext.context; PolyglotLanguage requiredPolyglotLanguage = context.engine.findLanguage(requiredLanguage); PolyglotLanguageContext requestedPolyglotLanguageContext = context.getContextInitialized(requiredPolyglotLanguage, languageContext.language); return LANGUAGE.getScope(requestedPolyglotLanguageContext.env); From 6e285cac85dae036c0f28472b9014f96aab4a3cb Mon Sep 17 00:00:00 2001 From: Christian Humer Date: Wed, 29 May 2024 18:00:18 +0200 Subject: [PATCH 4/7] Deprecate Env.isPolyglotEvalAllowed and add replacement with dedicated language. --- .../org/graalvm/polyglot/PolyglotAccess.java | 8 +- truffle/CHANGELOG.md | 1 + .../polyglot/ContextPolyglotAccessTest.java | 141 ++++++++++-------- .../ContextPreInitializationTest.java | 6 +- .../api/test/polyglot/LanguageSPITest.java | 2 +- .../oracle/truffle/api/TruffleLanguage.java | 80 ++++++---- .../com/oracle/truffle/api/impl/Accessor.java | 2 +- .../truffle/polyglot/EngineAccessor.java | 4 +- .../polyglot/PolyglotContextConfig.java | 3 - .../truffle/polyglot/PolyglotEngineImpl.java | 2 - .../polyglot/PolyglotLanguageContext.java | 35 +++-- 11 files changed, 167 insertions(+), 117 deletions(-) diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/PolyglotAccess.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/PolyglotAccess.java index f69394323bc0..67ba6737bec0 100644 --- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/PolyglotAccess.java +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/PolyglotAccess.java @@ -42,6 +42,7 @@ import java.util.Arrays; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Objects; import java.util.Set; @@ -263,7 +264,12 @@ public Builder allowEvalBetween(String... languages) { languageAccess = EconomicSet.create(); evalAccess.put(language, languageAccess); } - languageAccess.addAll(Arrays.asList(languages)); + Set filteredList = new LinkedHashSet<>(Arrays.asList(languages)); + // filter current language if it is not the only language + if (filteredList.size() > 1) { + filteredList.remove(language); + } + languageAccess.addAll(filteredList); } return this; } diff --git a/truffle/CHANGELOG.md b/truffle/CHANGELOG.md index 1bd10c6ae529..a38bee968bba 100644 --- a/truffle/CHANGELOG.md +++ b/truffle/CHANGELOG.md @@ -15,6 +15,7 @@ This changelog summarizes major changes between Truffle versions relevant to lan * GR-52930 Added `TruffleLanguage.Env.getHostLanguage()` returning the host language info. * GR-52930 Added `TruffleLanguage.Env.getScope(LanguageInfo)` returning the top scope object of the language. * GR-28866 Added `TruffleLanguage.Env.getScopePublic(LanguageInfo)` and `TruffleLanguage.Env.getScopeInternal(LanguageInfo)` to allow languages direct access to other language scopes to implement new polyglot builtins. +* GR-28866 Deprecated `TruffleLanguage.Env.isPolyglotEvalAllowed()`. Replace usages with `TruffleLanguage.Env.isPolyglotEvalAllowed(TruffleLanguage)`. Please see javadoc for the updated usage. ## Version 24.0.0 diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPolyglotAccessTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPolyglotAccessTest.java index 7594dbcdde57..772243c413ac 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPolyglotAccessTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPolyglotAccessTest.java @@ -125,8 +125,8 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje Env dependent = Dependent.getContext(DEPENDENT); assertPublicEvalDenied(language1, INTERNAL); - assertPublicEvalAllowed(language1, DEPENDENT); - assertPublicEvalAllowed(language1, LANGUAGE1); + assertPublicEvalAllowed(language1, DEPENDENT, true); + assertPublicEvalAllowed(language1, LANGUAGE1, true); assertPublicEvalDenied(language1, LANGUAGE2); assertInternalEvalAllowed(language1, INTERNAL); @@ -135,8 +135,8 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje assertInternalEvalDenied(language1, LANGUAGE2); assertPublicEvalDenied(dependent, INTERNAL); - assertPublicEvalAllowed(dependent, DEPENDENT); - assertPublicEvalAllowed(dependent, LANGUAGE1); + assertPublicEvalAllowed(dependent, DEPENDENT, true); + assertPublicEvalAllowed(dependent, LANGUAGE1, true); assertPublicEvalDenied(dependent, LANGUAGE2); assertInternalEvalAllowed(dependent, INTERNAL); @@ -144,6 +144,9 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje assertInternalEvalAllowed(dependent, LANGUAGE1); assertInternalEvalDenied(dependent, LANGUAGE2); + assertTrue(language1.isPolyglotEvalAllowed(null)); + assertTrue(dependent.isPolyglotEvalAllowed(null)); + return null; } } @@ -166,6 +169,8 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje Env env1 = Language1.getContext(LANGUAGE1); assertTrue(env1.getInternalLanguages().containsKey(LANGUAGE1)); assertFalse(env1.getInternalLanguages().containsKey(NOT_EXISTING_LANGUAGE)); + assertFalse(env1.getPublicLanguages().containsKey(LANGUAGE2)); + assertFalse(env1.getPublicLanguages().containsKey(DEPENDENT)); return null; } @@ -197,8 +202,8 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje assertPublicEvalDenied(language1, INTERNAL); assertPublicEvalDenied(language1, DEPENDENT); - assertPublicEvalAllowed(language1, LANGUAGE1); - assertPublicEvalAllowed(language1, LANGUAGE2); + assertPublicEvalAllowed(language1, LANGUAGE1, true); + assertPublicEvalAllowed(language1, LANGUAGE2, true); assertInternalEvalAllowed(language1, INTERNAL); assertInternalEvalAllowed(language1, DEPENDENT); @@ -207,8 +212,8 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje assertPublicEvalDenied(language2, INTERNAL); assertPublicEvalDenied(language2, DEPENDENT); - assertPublicEvalAllowed(language2, LANGUAGE1); - assertPublicEvalAllowed(language2, LANGUAGE2); + assertPublicEvalAllowed(language2, LANGUAGE1, true); + assertPublicEvalAllowed(language2, LANGUAGE2, true); assertInternalEvalAllowed(language2, INTERNAL); assertInternalEvalDenied(language2, DEPENDENT); @@ -217,6 +222,9 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje testPolyglotAccess(language1, language2); + assertTrue(language1.isPolyglotEvalAllowed(null)); + assertTrue(language2.isPolyglotEvalAllowed(null)); + return null; } } @@ -327,7 +335,7 @@ private static void testNoAccessImpl() { assertPublicEvalDenied(language1, INTERNAL); assertPublicEvalDenied(language1, DEPENDENT); - assertPublicEvalAllowed(language1, LANGUAGE1); + assertPublicEvalAllowed(language1, LANGUAGE1, false); assertPublicEvalDenied(language1, LANGUAGE2); assertInternalEvalAllowed(language1, INTERNAL); @@ -338,7 +346,7 @@ private static void testNoAccessImpl() { assertPublicEvalDenied(language2, INTERNAL); assertPublicEvalDenied(language2, DEPENDENT); assertPublicEvalDenied(language2, LANGUAGE1); - assertPublicEvalAllowed(language2, LANGUAGE2); + assertPublicEvalAllowed(language2, LANGUAGE2, false); assertInternalEvalAllowed(language2, INTERNAL); assertInternalEvalDenied(language2, DEPENDENT); @@ -347,8 +355,8 @@ private static void testNoAccessImpl() { assertBindingsDenied(language1); assertBindingsDenied(language2); - assertNoEvalAccess(language1); - assertNoEvalAccess(language2); + assertFalse(language1.isPolyglotEvalAllowed(null)); + assertFalse(language2.isPolyglotEvalAllowed(null)); } private static void assertImportNotAcccessible(Env env1) { @@ -470,8 +478,8 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje assertPublicEvalDenied(language1, INTERNAL); assertPublicEvalDenied(language1, DEPENDENT); - assertPublicEvalAllowed(language1, LANGUAGE1); - assertPublicEvalAllowed(language1, LANGUAGE2); + assertPublicEvalAllowed(language1, LANGUAGE1, true); + assertPublicEvalAllowed(language1, LANGUAGE2, true); assertInternalEvalAllowed(language1, INTERNAL); assertInternalEvalAllowed(language1, DEPENDENT); @@ -481,14 +489,15 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje assertPublicEvalDenied(language2, INTERNAL); assertPublicEvalDenied(language2, DEPENDENT); assertPublicEvalDenied(language2, LANGUAGE1); - assertPublicEvalAllowed(language2, LANGUAGE2); + assertPublicEvalAllowed(language2, LANGUAGE2, false); assertInternalEvalAllowed(language2, INTERNAL); assertInternalEvalDenied(language2, DEPENDENT); assertInternalEvalDenied(language2, LANGUAGE1); assertInternalEvalAllowed(language2, LANGUAGE2); - assertNoEvalAccess(language2); + assertTrue(language1.isPolyglotEvalAllowed(null)); + assertFalse(language2.isPolyglotEvalAllowed(null)); return null; } @@ -516,7 +525,7 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje assertPublicEvalDenied(language1, INTERNAL); assertPublicEvalDenied(language1, DEPENDENT); - assertPublicEvalAllowed(language1, LANGUAGE1); + assertPublicEvalAllowed(language1, LANGUAGE1, true); assertPublicEvalDenied(language1, LANGUAGE2); assertInternalEvalAllowed(language1, INTERNAL); @@ -527,15 +536,15 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje assertPublicEvalDenied(language2, INTERNAL); assertPublicEvalDenied(language2, DEPENDENT); assertPublicEvalDenied(language2, LANGUAGE1); - assertPublicEvalAllowed(language2, LANGUAGE2); + assertPublicEvalAllowed(language2, LANGUAGE2, false); assertInternalEvalAllowed(language2, INTERNAL); assertInternalEvalDenied(language2, DEPENDENT); assertInternalEvalDenied(language2, LANGUAGE1); assertInternalEvalAllowed(language2, LANGUAGE2); - assertNoEvalAccess(language1); - assertNoEvalAccess(language2); + assertFalse(language1.isPolyglotEvalAllowed(null)); + assertFalse(language2.isPolyglotEvalAllowed(null)); return null; } @@ -563,8 +572,8 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje assertPublicEvalDenied(language1, INTERNAL); assertPublicEvalDenied(language1, DEPENDENT); - assertPublicEvalAllowed(language1, LANGUAGE1); - assertPublicEvalAllowed(language1, LANGUAGE2); + assertPublicEvalAllowed(language1, LANGUAGE1, true); + assertPublicEvalAllowed(language1, LANGUAGE2, true); assertInternalEvalAllowed(language1, INTERNAL); assertInternalEvalAllowed(language1, DEPENDENT); @@ -573,14 +582,17 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje assertPublicEvalDenied(language2, INTERNAL); assertPublicEvalDenied(language2, DEPENDENT); - assertPublicEvalAllowed(language2, LANGUAGE1); - assertPublicEvalAllowed(language2, LANGUAGE2); + assertPublicEvalAllowed(language2, LANGUAGE1, true); + assertPublicEvalAllowed(language2, LANGUAGE2, true); assertInternalEvalAllowed(language2, INTERNAL); assertInternalEvalDenied(language2, DEPENDENT); assertInternalEvalAllowed(language2, LANGUAGE1); assertInternalEvalAllowed(language2, LANGUAGE2); + assertTrue(language1.isPolyglotEvalAllowed(null)); + assertTrue(language2.isPolyglotEvalAllowed(null)); + return null; } } @@ -607,7 +619,7 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje assertPublicEvalDenied(language1, INTERNAL); assertPublicEvalDenied(language1, DEPENDENT); - assertPublicEvalAllowed(language1, LANGUAGE1); + assertPublicEvalAllowed(language1, LANGUAGE1, true); assertPublicEvalDenied(language1, LANGUAGE2); assertInternalEvalAllowed(language1, INTERNAL); @@ -618,15 +630,15 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje assertPublicEvalDenied(language2, INTERNAL); assertPublicEvalDenied(language2, DEPENDENT); assertPublicEvalDenied(language2, LANGUAGE1); - assertPublicEvalAllowed(language2, LANGUAGE2); + assertPublicEvalAllowed(language2, LANGUAGE2, false); assertInternalEvalAllowed(language2, INTERNAL); assertInternalEvalDenied(language2, DEPENDENT); assertInternalEvalDenied(language2, LANGUAGE1); assertInternalEvalAllowed(language2, LANGUAGE2); - assertNoEvalAccess(language1); - assertNoEvalAccess(language2); + assertTrue(language1.isPolyglotEvalAllowed(null)); + assertFalse(language2.isPolyglotEvalAllowed(null)); return null; } @@ -655,9 +667,9 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje assertPublicEvalDenied(language1, INTERNAL); assertPublicEvalDenied(language1, DEPENDENT); - assertPublicEvalAllowed(language1, LANGUAGE1); - assertPublicEvalAllowed(language1, LANGUAGE2); - assertPublicEvalAllowed(language1, LANGUAGE3); + assertPublicEvalAllowed(language1, LANGUAGE1, true); + assertPublicEvalAllowed(language1, LANGUAGE2, true); + assertPublicEvalAllowed(language1, LANGUAGE3, true); assertInternalEvalAllowed(language1, INTERNAL); assertInternalEvalAllowed(language1, DEPENDENT); @@ -667,9 +679,9 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje assertPublicEvalDenied(language2, INTERNAL); assertPublicEvalDenied(language2, DEPENDENT); - assertPublicEvalAllowed(language2, LANGUAGE1); - assertPublicEvalAllowed(language2, LANGUAGE2); - assertPublicEvalAllowed(language2, LANGUAGE3); + assertPublicEvalAllowed(language2, LANGUAGE1, true); + assertPublicEvalAllowed(language2, LANGUAGE2, true); + assertPublicEvalAllowed(language2, LANGUAGE3, true); assertInternalEvalAllowed(language2, INTERNAL); assertInternalEvalDenied(language2, DEPENDENT); @@ -679,9 +691,9 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje assertPublicEvalDenied(language3, INTERNAL); assertPublicEvalDenied(language3, DEPENDENT); - assertPublicEvalAllowed(language3, LANGUAGE1); - assertPublicEvalAllowed(language3, LANGUAGE2); - assertPublicEvalAllowed(language3, LANGUAGE3); + assertPublicEvalAllowed(language3, LANGUAGE1, true); + assertPublicEvalAllowed(language3, LANGUAGE2, true); + assertPublicEvalAllowed(language3, LANGUAGE3, true); assertInternalEvalAllowed(language3, INTERNAL); assertInternalEvalDenied(language3, DEPENDENT); @@ -689,6 +701,10 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje assertInternalEvalAllowed(language3, LANGUAGE2); assertInternalEvalAllowed(language3, LANGUAGE3); + assertTrue(language1.isPolyglotEvalAllowed(null)); + assertTrue(language2.isPolyglotEvalAllowed(null)); + assertTrue(language3.isPolyglotEvalAllowed(null)); + return null; } } @@ -717,9 +733,9 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje assertPublicEvalDenied(language1, INTERNAL); assertPublicEvalDenied(language1, DEPENDENT); - assertPublicEvalAllowed(language1, LANGUAGE1); + assertPublicEvalAllowed(language1, LANGUAGE1, true); assertPublicEvalDenied(language1, LANGUAGE2); - assertPublicEvalAllowed(language1, LANGUAGE3); + assertPublicEvalAllowed(language1, LANGUAGE3, true); assertInternalEvalAllowed(language1, INTERNAL); assertInternalEvalAllowed(language1, DEPENDENT); @@ -730,8 +746,8 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje assertPublicEvalDenied(language2, INTERNAL); assertPublicEvalDenied(language2, DEPENDENT); assertPublicEvalDenied(language2, LANGUAGE1); - assertPublicEvalAllowed(language2, LANGUAGE2); - assertPublicEvalAllowed(language2, LANGUAGE3); + assertPublicEvalAllowed(language2, LANGUAGE2, true); + assertPublicEvalAllowed(language2, LANGUAGE3, true); assertInternalEvalAllowed(language2, INTERNAL); assertInternalEvalDenied(language2, DEPENDENT); @@ -741,9 +757,9 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje assertPublicEvalDenied(language3, INTERNAL); assertPublicEvalDenied(language3, DEPENDENT); - assertPublicEvalAllowed(language3, LANGUAGE1); - assertPublicEvalAllowed(language3, LANGUAGE2); - assertPublicEvalAllowed(language3, LANGUAGE3); + assertPublicEvalAllowed(language3, LANGUAGE1, true); + assertPublicEvalAllowed(language3, LANGUAGE2, true); + assertPublicEvalAllowed(language3, LANGUAGE3, true); assertInternalEvalAllowed(language3, INTERNAL); assertInternalEvalDenied(language3, DEPENDENT); @@ -751,6 +767,10 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje assertInternalEvalAllowed(language3, LANGUAGE2); assertInternalEvalAllowed(language3, LANGUAGE3); + assertTrue(language1.isPolyglotEvalAllowed(null)); + assertTrue(language2.isPolyglotEvalAllowed(null)); + assertTrue(language3.isPolyglotEvalAllowed(null)); + return null; } } @@ -781,7 +801,7 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje assertPublicEvalDenied(language1, INTERNAL); assertPublicEvalDenied(language1, DEPENDENT); - assertPublicEvalAllowed(language1, LANGUAGE1); + assertPublicEvalAllowed(language1, LANGUAGE1, false); assertPublicEvalDenied(language1, LANGUAGE2); assertInternalEvalAllowed(language1, INTERNAL); @@ -791,15 +811,16 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje assertPublicEvalDenied(language2, INTERNAL); assertPublicEvalDenied(language2, DEPENDENT); - assertPublicEvalAllowed(language2, LANGUAGE1); - assertPublicEvalAllowed(language2, LANGUAGE2); + assertPublicEvalAllowed(language2, LANGUAGE1, true); + assertPublicEvalAllowed(language2, LANGUAGE2, true); assertInternalEvalAllowed(language2, INTERNAL); assertInternalEvalDenied(language2, DEPENDENT); assertInternalEvalAllowed(language2, LANGUAGE1); assertInternalEvalAllowed(language2, LANGUAGE2); - assertNoEvalAccess(language1); + assertFalse(language1.isPolyglotEvalAllowed(null)); + assertTrue(language2.isPolyglotEvalAllowed(null)); return null; } @@ -946,9 +967,9 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje Env language1 = Language1.getContext(LANGUAGE1); assertPublicEvalDenied(language1, INTERNAL); - assertPublicEvalAllowed(language1, DEPENDENT); - assertPublicEvalAllowed(language1, LANGUAGE1); - assertPublicEvalAllowed(language1, LANGUAGE2); + assertPublicEvalAllowed(language1, DEPENDENT, true); + assertPublicEvalAllowed(language1, LANGUAGE1, true); + assertPublicEvalAllowed(language1, LANGUAGE2, true); assertInternalEvalAllowed(language1, INTERNAL); assertInternalEvalAllowed(language1, DEPENDENT); @@ -977,7 +998,7 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje assertPublicEvalDenied(language1, INTERNAL); assertPublicEvalDenied(language1, DEPENDENT); - assertPublicEvalAllowed(language1, LANGUAGE1); + assertPublicEvalAllowed(language1, LANGUAGE1, false); assertPublicEvalDenied(language1, LANGUAGE2); assertInternalEvalAllowed(language1, INTERNAL); @@ -1008,8 +1029,8 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje assertPublicEvalDenied(language1, INTERNAL); assertPublicEvalDenied(language1, DEPENDENT); - assertPublicEvalAllowed(language1, LANGUAGE1); - assertPublicEvalAllowed(language1, LANGUAGE2); + assertPublicEvalAllowed(language1, LANGUAGE1, true); + assertPublicEvalAllowed(language1, LANGUAGE2, true); assertInternalEvalAllowed(language1, INTERNAL); assertInternalEvalAllowed(language1, DEPENDENT); @@ -1019,7 +1040,7 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje assertPublicEvalDenied(language2, INTERNAL); assertPublicEvalDenied(language2, DEPENDENT); assertPublicEvalDenied(language2, LANGUAGE1); - assertPublicEvalAllowed(language2, LANGUAGE2); + assertPublicEvalAllowed(language2, LANGUAGE2, false); assertInternalEvalAllowed(language2, INTERNAL); assertInternalEvalDenied(language2, DEPENDENT); @@ -1039,10 +1060,6 @@ public void testParsePublic3() { evalTestLanguage(context, ParsePublic3TestLanguage.class, ""); } - private static void assertNoEvalAccess(Env env) { - assertFalse(env.isPolyglotEvalAllowed()); - } - private static void assertBindingsDenied(Env env) { assertFalse(env.isPolyglotBindingsAccessAllowed()); assertExportNotAcccessible(env); @@ -1088,13 +1105,11 @@ private static void assertPublicEvalDenied(Env env, String targetId) { } } - private static void assertPublicEvalAllowed(Env env, String targetId) { + private static void assertPublicEvalAllowed(Env env, String targetId, boolean polyglotAccess) { LanguageInfo info = env.getPublicLanguages().get(targetId); assertNotNull(info); assertNotNull(env.parsePublic(Source.newBuilder(targetId, "", "").build())); - if (env.getPublicLanguages().size() > 1) { - assertTrue(env.isPolyglotEvalAllowed()); - } + assertEquals(polyglotAccess, env.isPolyglotEvalAllowed(info)); assertNotNull(env.getScopePublic(info)); } diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPreInitializationTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPreInitializationTest.java index d70e8dae3b9e..b3b216b83b85 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPreInitializationTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPreInitializationTest.java @@ -1836,7 +1836,7 @@ public void testCodeSharingTwoLayers() throws Exception { assertTrue(env.isCreateThreadAllowed()); assertFalse(env.isHostLookupAllowed()); assertTrue(env.isNativeAccessAllowed()); - assertTrue(env.isPolyglotEvalAllowed()); + assertTrue(env.isPolyglotEvalAllowed(null)); assertTrue(env.isPolyglotBindingsAccessAllowed()); assertEquals(testId, env.getTimeZone()); firstContextInitialized.set(true); @@ -1846,7 +1846,7 @@ public void testCodeSharingTwoLayers() throws Exception { assertFalse(env.isCreateThreadAllowed()); assertFalse(env.isHostLookupAllowed()); assertFalse(env.isNativeAccessAllowed()); - assertFalse(env.isPolyglotEvalAllowed()); + assertFalse(env.isPolyglotEvalAllowed(null)); assertFalse(env.isPolyglotBindingsAccessAllowed()); assertFalse(env.getOptions().get(ContextPreInitializationTestSharedLanguage.Option1)); assertEquals(systemDefault, env.getTimeZone()); @@ -1970,7 +1970,7 @@ public void testCodeSharingCommonConfig() throws Exception { assertFalse(env.isHostLookupAllowed()); assertFalse(env.isNativeAccessAllowed()); // polyglot access currently defaults to true for preinit. See GR-14657. - assertTrue(env.isPolyglotEvalAllowed()); + assertTrue(env.isPolyglotEvalAllowed(null)); assertTrue(env.isPolyglotBindingsAccessAllowed()); assertEquals(systemDefault, env.getTimeZone()); firstContextInitialized.set(true); diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageSPITest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageSPITest.java index e2b288a7d138..e375aa0a487b 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageSPITest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/LanguageSPITest.java @@ -997,7 +997,7 @@ private static Boolean getPrivilege(Env env, int privilege) { case CREATE_THREAD: return env.isCreateThreadAllowed(); case POLYGLOT_ACCESS: - return env.isPolyglotBindingsAccessAllowed() || env.isPolyglotEvalAllowed(); + return env.isPolyglotBindingsAccessAllowed() || env.isPolyglotEvalAllowed(null); case ENVIRONMENT_ACCESS: // environment access can only be observed with properties String value = env.getEnvironment().get(OUTER_CONTEXT_TEST_KEY); diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java index 439873bceb12..428852b32d2a 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java @@ -2476,20 +2476,43 @@ public boolean isNativeAccessAllowed() { } /** - * Returns true if polyglot evaluation is allowed, else false. - * Guest languages should hide or disable all polyglot evaluation builtins if this flag is - * set to false. Note that if polyglot evaluation access is disabled, then the - * {@link #getInternalLanguages() available languages list} only shows the current language, - * {@link Registration#dependentLanguages() dependent languages} and - * {@link Registration#internal() internal languages}. * - * @see org.graalvm.polyglot.Context.Builder#allowPolyglotAccess(org.graalvm.polyglot.PolyglotAccess) * @since 19.2 + * @deprecated in 24.1 use {@link #isPolyglotEvalAllowed(LanguageInfo) + * isPolyglotEvalAllowed(null) instead}. Note that language implementations + * should now check whether polyglot eval is allowed also for individual + * languages, as access could be denied only for an individual language. */ @TruffleBoundary + @Deprecated public boolean isPolyglotEvalAllowed() { + return isPolyglotEvalAllowed(null); + } + + /** + * Returns true if the current language is allowed to evaluate guest + * application provided code of the given language, else false. If this method + * returns true then the current language has permission to use + * {@link #parsePublic(Source, String...)} and {@link #getScopePublic(LanguageInfo)} for the + * given language. If the given language is null then this method will return + * true if polyglot access is allowed in principle, else false. + * Languages may want to call this method twice. Once with null to determine + * whether polyglot eval and scope based builtins should be available to the application at + * all and once with the concrete language just before the access. + *

+ * The result of this method is safe to be cached per language context, it is guaranteed to + * not change for a context and target language combination. + * + * @see PolyglotAccess.Builder#allowEval(String, String) Embedders can restrict polyglot + * eval access between certain languages. + * @see #parsePublic(Source, String...) + * @see #getScopePublic(LanguageInfo) + * @since 24.1 + */ + @TruffleBoundary + public boolean isPolyglotEvalAllowed(LanguageInfo targetLanguage) { try { - return LanguageAccessor.engineAccess().isPolyglotEvalAllowed(polyglotLanguageContext); + return LanguageAccessor.engineAccess().isPolyglotEvalAllowed(polyglotLanguageContext, targetLanguage); } catch (Throwable t) { throw engineToLanguageException(t); } @@ -2518,10 +2541,9 @@ public boolean isPolyglotBindingsAccessAllowed() { * Allows it to be determined if this {@link org.graalvm.polyglot.Context} can execute code * written in a language with a given MIME type. * + * @return a boolean that indicates if the MIME type is supported * @see Source#getMimeType() * @see #parsePublic(Source, String...) - * - * @return a boolean that indicates if the MIME type is supported * @since 0.11 */ @TruffleBoundary @@ -2543,7 +2565,10 @@ public boolean isMimeTypeSupported(String mimeType) { * source to reference the actual parameters passed to * {@link CallTarget#call(java.lang.Object...)}. *

- * Compared to {@link #parsePublic(Source, String...)} this method provides also access to + * The suffix internal in the method name indicates that the result of this + * method is not safe to exposed to arbitrary guest code, by default. Use + * {@link #parsePublic(Source, String...)} for that purpose instead. Compared to + * {@link #parsePublic(Source, String...)} this method provides also access to * {@link TruffleLanguage.Registration#internal() internal} and dependent languages in * addition to public languages. For example, in JavaScript, a call to the eval builtin * should forward to {@link #parsePublic(Source, String...)} as it contains code provided by @@ -2562,6 +2587,8 @@ public boolean isMimeTypeSupported(String mimeType) { * @return the call target representing the parsed result * @throws IllegalStateException if polyglot context associated with this environment is not * entered + * @throws IllegalArgumentException if the language is not allowed to evaluate code by the + * current language. * @see #parsePublic(Source, String...) * @since 19.2 */ @@ -2585,10 +2612,10 @@ public CallTarget parseInternal(Source source, String... argumentNames) { * source to reference the actual parameters passed to * {@link CallTarget#call(java.lang.Object...)}. *

- * Compared to {@link #parseInternal(Source, String...)} this method does only provide - * access to non internal, non dependent, public languages. Public languages are configured - * by the embedder to be accessible to the guest language program. For example, in - * JavaScript, a call to the eval builtin should forward to + * The suffix public in the method name indicates that the result of this + * method is safe to be exposed by default to guest applications. Public languages are + * configured by the embedder to be accessible to the guest language program. For example, + * in JavaScript, a call to the eval builtin should forward to * {@link #parsePublic(Source, String...)} as it contains code provided by the guest * language user. Parsing regular expressions with the internal regular expression engine * should call {@link #parseInternal(Source, String...)} instead, as this is considered an @@ -2665,7 +2692,7 @@ public OutputStream err() { * language} may also be associated with additional services. One can request * implementations of such services by calling this method with the type identifying the * requested service and its API. - * + *

* Services that can be obtained via this method include * {@link com.oracle.truffle.api.instrumentation.Instrumenter} and others. * @@ -2948,13 +2975,13 @@ public TruffleFile getPublicTruffleFile(URI uri) { * * @param path the absolute or relative path to create {@link TruffleFile} for * @return {@link TruffleFile} - * @since 19.3.0 * @throws UnsupportedOperationException when the {@link FileSystem} supports only * {@link URI} * @throws IllegalArgumentException if the {@code path} string cannot be converted to a * {@link Path} * @see #getTruffleFileInternal(String, Predicate) * @see #getPublicTruffleFile(java.lang.String) + * @since 19.3.0 */ @TruffleBoundary public TruffleFile getInternalTruffleFile(String path) { @@ -2975,13 +3002,13 @@ public TruffleFile getInternalTruffleFile(String path) { * * @param uri the {@link URI} to create {@link TruffleFile} for * @return {@link TruffleFile} - * @since 19.3.0 * @throws UnsupportedOperationException when {@link URI} scheme is not supported * @throws IllegalArgumentException if preconditions on the {@code uri} do not hold. * @throws java.nio.file.FileSystemNotFoundException is the file system, identified by the * {@code uri}, does not exist and cannot be created automatically * @see #getTruffleFileInternal(URI, Predicate) * @see #getPublicTruffleFile(java.net.URI) + * @since 19.3.0 */ @TruffleBoundary public TruffleFile getInternalTruffleFile(URI uri) { @@ -3036,11 +3063,10 @@ public TruffleFile getInternalTruffleFile(URI uri) { * {@link URI} * @throws IllegalArgumentException if the {@code path} string cannot be converted to a * {@link Path} - * @since 21.1.0 * @see #getTruffleFileInternal(URI, Predicate) * @see #getPublicTruffleFile(String) * @see #getInternalTruffleFile(String) - * + * @since 21.1.0 */ @TruffleBoundary public TruffleFile getTruffleFileInternal(String path, Predicate filter) { @@ -3061,11 +3087,10 @@ public TruffleFile getTruffleFileInternal(String path, Predicate fi * @throws IllegalArgumentException if preconditions on the {@code uri} do not hold. * @throws java.nio.file.FileSystemNotFoundException is the file system, identified by the * {@code uri}, does not exist and cannot be created automatically - * @since 21.1.0 * @see #getTruffleFileInternal(String, Predicate) * @see #getPublicTruffleFile(URI) * @see #getInternalTruffleFile(URI) - * + * @since 21.1.0 */ @TruffleBoundary public TruffleFile getTruffleFileInternal(URI uri, Predicate filter) { @@ -3480,7 +3505,6 @@ public Object createHostAdapterClassWithStaticOverrides(Class[] types, Object * @throws UnsupportedOperationException if creating adapter classes is not supported on * this runtime at all, which is currently the case for native images. * @throws NullPointerException if {@code types} is null - * * @see #createHostAdapterWithClassOverrides(Object[], Object) * @since 22.1 */ @@ -3522,7 +3546,6 @@ public Object createHostAdapter(Object[] types) { * @throws UnsupportedOperationException if creating adapter classes is not supported on * this runtime at all, which is currently the case for native images. * @throws NullPointerException if either {@code types} or {@code classOverrides} is null. - * * @see #createHostAdapter(Object[]) * @since 22.1 */ @@ -3600,7 +3623,6 @@ public TruffleFile getInternalResource(String resourceId) throws IOException { * empty a root logger for language or instrument is returned * @return a {@link TruffleLogger} * @since 21.1 - * */ @TruffleBoundary public TruffleLogger getLogger(String loggerName) { @@ -3771,7 +3793,6 @@ public SandboxPolicy getSandboxPolicy() { * @see #getScopeInternal(LanguageInfo) * @see #isPolyglotEvalAllowed(LanguageInfo) * @see #getPolyglotBindings() - * * @since 24.1 */ @TruffleBoundary @@ -3809,12 +3830,12 @@ public Object getScopePublic(LanguageInfo language) throws IllegalArgumentExcept * {@link #getPublicLanguages() public languages} with * {@link #isPolyglotEvalAllowed(LanguageInfo) eval permissions}. * - * @see #getScopePublic(LanguageInfo) * @return the scope, or null if the requested language does not support such a * concept * @throws IllegalStateException if polyglot context associated with this environment is not * entered * @throws SecurityException if polyglot scope access is not enabled for this language. + * @see #getScopePublic(LanguageInfo) * @since 24.1 */ @TruffleBoundary @@ -3951,7 +3972,7 @@ static RuntimeException engineToLanguageException(T * current {@link Node}, if available, as parameter. *

* Example intended usage: - * + *

* See {@link ContextReference} for a full usage example. * * @since 0.25 revised in 21.3 @@ -4243,15 +4264,14 @@ public enum ContextPolicy { /** * Mode of exit operation. * - * @since 22.0 * @see #exitContext(Object, ExitMode, int) + * @since 22.0 */ public enum ExitMode { /** * Natural exit that occurs during normal context close. * * @since 22.0 - * */ NATURAL, /** diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java index 9f946a6690cb..96181e95fa4c 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java @@ -545,7 +545,7 @@ public abstract TruffleContext createInternalContext(Object sourcePolyglotLangua public abstract FileSystem getFileSystem(Object polyglotContext); - public abstract boolean isPolyglotEvalAllowed(Object polyglotLanguageContext); + public abstract boolean isPolyglotEvalAllowed(Object polyglotLanguageContext, LanguageInfo language); public abstract boolean isPolyglotBindingsAccessAllowed(Object polyglotLanguageContext); diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java index df56bdb0649f..396ef76ad74a 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java @@ -237,9 +237,9 @@ public boolean hasCurrentContext() { } @Override - public boolean isPolyglotEvalAllowed(Object polyglotLanguageContext) { + public boolean isPolyglotEvalAllowed(Object polyglotLanguageContext, LanguageInfo language) { PolyglotLanguageContext languageContext = ((PolyglotLanguageContext) polyglotLanguageContext); - return languageContext.isPolyglotEvalAllowed(null); + return languageContext.isPolyglotEvalAllowed(language); } @Override diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextConfig.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextConfig.java index d0a7a80b7741..51ac382ecaeb 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextConfig.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextConfig.java @@ -418,9 +418,6 @@ boolean isAccessPermitted(PolyglotLanguage from, PolyglotLanguage to) { return true; } } else { - if (from == to) { - return true; - } Set configuredAccess = from.engine.getAPIAccess().getEvalAccess(polyglotAccess, from.getId()); if (configuredAccess != null && configuredAccess.contains(to.getId())) { return true; diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineImpl.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineImpl.java index ed5a11f2a529..a729a25207a8 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineImpl.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotEngineImpl.java @@ -887,8 +887,6 @@ PolyglotLanguage findLanguage(PolyglotLanguageContext accessingLanguage, String } } - assert allowInternalAndDependent || foundLanguage == null || (!foundLanguage.isInternal() && accessingLanguage.isPolyglotEvalAllowed(languageId)); - if (foundLanguage != null) { return idToLanguage.get(foundLanguage.getId()); } diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguageContext.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguageContext.java index 7897b9f4a36d..90d1b327630b 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguageContext.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguageContext.java @@ -241,20 +241,33 @@ boolean isPolyglotBindingsAccessAllowed() { return accessibleLanguages.contains(language.getId()); } - boolean isPolyglotEvalAllowed(String targetLanguage) { - if (context.config.polyglotAccess == language.getAPIAccess().getPolyglotAccessAll()) { - return true; - } else if (targetLanguage != null && language.getId().equals(targetLanguage)) { - return true; + boolean isPolyglotEvalAllowed(LanguageInfo info) { + Map> allAccess = getAPIAccess().getEvalAccess(context.config.polyglotAccess); + if (allAccess != null && allAccess.size() == 0) { + return false; } - Set accessibleLanguages = getAPIAccess().getEvalAccess(context.config.polyglotAccess, - language.getId()); - if (accessibleLanguages == null || accessibleLanguages.isEmpty()) { + Set languageAccess = null; + if (allAccess != null) { + languageAccess = allAccess.get(language.getId()); + if (languageAccess != null && languageAccess.size() == 0) { + return false; + } + } + + if (languageAccess == null && allAccess != null && allAccess.size() != 0) { + // there are other languages configured but this language has no access. return false; - } else if (accessibleLanguages.size() > 1 || !accessibleLanguages.iterator().next().equals(language.getId())) { - return targetLanguage == null || accessibleLanguages.contains(targetLanguage); } - return false; + + if (info == null) { + return true; + } else { + if (languageAccess != null && !info.getId().equals(language.getId()) && !languageAccess.contains(info.getId())) { + // check whether the target language is included + return false; + } + return getAccessibleLanguages(false).containsKey(info.getId()); + } } Thread.UncaughtExceptionHandler getPolyglotExceptionHandler() { From b85c100ef7ae11922e9c20843af5a071ce3a3d22 Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Thu, 30 May 2024 09:21:52 +0200 Subject: [PATCH 5/7] Post merge fixes. Resolved GR-28866 review comments. --- .../org/graalvm/polyglot/PolyglotAccess.java | 4 +- truffle/CHANGELOG.md | 4 +- .../polyglot/ContextPolyglotAccessTest.java | 2 +- .../oracle/truffle/api/TruffleLanguage.java | 43 +++++++++++++------ .../polyglot/PolyglotLanguageContext.java | 21 +-------- 5 files changed, 37 insertions(+), 37 deletions(-) diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/PolyglotAccess.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/PolyglotAccess.java index 67ba6737bec0..5b440bf3f38f 100644 --- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/PolyglotAccess.java +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/PolyglotAccess.java @@ -246,7 +246,7 @@ public final class Builder { * more than two then all language evaluation combinations will be allowed. This method * potentially overrides already configured access rights with * {@link #allowEval(String, String)} or {@link #denyEval(String, String)}. The given - * language array must be null and individual languages must not be + * language array must be non null and individual languages must not be * null. * * @see #allowEval(String, String) @@ -282,7 +282,7 @@ public Builder allowEvalBetween(String... languages) { * more than two then all language access combinations will be denied. This method * potentially overrides already configured access rights with * {@link #allowEval(String, String)} or {@link #denyEval(String, String)}. The given - * language array must be null and individual languages must not be + * language array must be non null and individual languages must not be * null. * * @see #denyEval(String, String) diff --git a/truffle/CHANGELOG.md b/truffle/CHANGELOG.md index a38bee968bba..81fdda5c338d 100644 --- a/truffle/CHANGELOG.md +++ b/truffle/CHANGELOG.md @@ -12,10 +12,8 @@ This changelog summarizes major changes between Truffle versions relevant to lan * GR-38322 Added `--engine.TraceMissingSafepointPollInterval=N` to show Java stacktraces when there are [missing `TruffleSafepoint.poll()` calls](https://github.com/oracle/graal/blob/master/truffle/docs/Safepoints.md#find-missing-safepoint-polls). * GR-52644 Deprecated `TruffleLanguage.Registration.needsAllEncodings`, no longer needs to be declared. It is sufficient for a language module to require `org.graalvm.shadowed.jcodings` to enable all string encodings. * GR-51172 Add `CompilerDirectives.ensureAllocatedHere` to mark an allocation as non-movable. This allows language developers to mark special allocations as non-optimizable to allow better control for allocations potentially throwing OutOfMemoryErrors. -* GR-52930 Added `TruffleLanguage.Env.getHostLanguage()` returning the host language info. -* GR-52930 Added `TruffleLanguage.Env.getScope(LanguageInfo)` returning the top scope object of the language. * GR-28866 Added `TruffleLanguage.Env.getScopePublic(LanguageInfo)` and `TruffleLanguage.Env.getScopeInternal(LanguageInfo)` to allow languages direct access to other language scopes to implement new polyglot builtins. -* GR-28866 Deprecated `TruffleLanguage.Env.isPolyglotEvalAllowed()`. Replace usages with `TruffleLanguage.Env.isPolyglotEvalAllowed(TruffleLanguage)`. Please see javadoc for the updated usage. +* GR-28866 Deprecated `TruffleLanguage.Env.isPolyglotEvalAllowed()`. Replace usages with `TruffleLanguage.Env.isPolyglotEvalAllowed(LanguageInfo)`. Please see javadoc for the updated usage. ## Version 24.0.0 diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPolyglotAccessTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPolyglotAccessTest.java index 772243c413ac..e9dae1e9c560 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPolyglotAccessTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/ContextPolyglotAccessTest.java @@ -543,7 +543,7 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje assertInternalEvalDenied(language2, LANGUAGE1); assertInternalEvalAllowed(language2, LANGUAGE2); - assertFalse(language1.isPolyglotEvalAllowed(null)); + assertTrue(language1.isPolyglotEvalAllowed(null)); assertFalse(language2.isPolyglotEvalAllowed(null)); return null; diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java index 428852b32d2a..3dd2f1aa7711 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java @@ -1425,6 +1425,8 @@ protected void disposeThread(C context, Thread thread) { *

  • Top scopes available in the {@link org.graalvm.polyglot polyglot API} as context * {@link Context#getBindings(String) bindings} object. Access to members of the bindings object * is applied to the returned scope object via interop. + *
  • Languages may expose other language scopes using a polyglot bindings builtin. E.g with + * {@link com.oracle.truffle.api.TruffleLanguage.Env#getScopePublic(LanguageInfo)}. * *

    * @@ -2541,9 +2543,10 @@ public boolean isPolyglotBindingsAccessAllowed() { * Allows it to be determined if this {@link org.graalvm.polyglot.Context} can execute code * written in a language with a given MIME type. * - * @return a boolean that indicates if the MIME type is supported * @see Source#getMimeType() * @see #parsePublic(Source, String...) + * + * @return a boolean that indicates if the MIME type is supported * @since 0.11 */ @TruffleBoundary @@ -2586,9 +2589,10 @@ public boolean isMimeTypeSupported(String mimeType) { * that can be referenced from the source * @return the call target representing the parsed result * @throws IllegalStateException if polyglot context associated with this environment is not - * entered + * entered, or if the language is neither a {@link #getPublicLanguages() public + * language} nor an {@link #getInternalLanguages() internal language}. * @throws IllegalArgumentException if the language is not allowed to evaluate code by the - * current language. + * current language * @see #parsePublic(Source, String...) * @since 19.2 */ @@ -2625,13 +2629,21 @@ public CallTarget parseInternal(Source source, String... argumentNames) { * {@link Env#parseInternal(Source, String...)} instead of directly passing the Source to * the parser, in order to support code caching with {@link ContextPolicy#SHARED} and * {@link ContextPolicy#REUSE}. + *

    + * Languages should check for {@link #isPolyglotEvalAllowed(LanguageInfo) eval permissions} + * for each {@link #getPublicLanguages() public language} prior to calling this method, + * otherwise {@link IllegalArgumentException} is thrown if not sufficient privileges are + * available. * * @param source the source to evaluate * @param argumentNames the names of {@link CallTarget#call(java.lang.Object...)} arguments * that can be referenced from the source * @return the call target representing the parsed result * @throws IllegalStateException if polyglot context associated with this environment is not - * entered + * entered, or if the language is not a {@link #getPublicLanguages() public + * language} + * @throws IllegalArgumentException if the language is not allowed to evaluate code by the + * current language * @see #parseInternal(Source, String...) * @since 19.2 */ @@ -2692,7 +2704,7 @@ public OutputStream err() { * language} may also be associated with additional services. One can request * implementations of such services by calling this method with the type identifying the * requested service and its API. - *

    + * * Services that can be obtained via this method include * {@link com.oracle.truffle.api.instrumentation.Instrumenter} and others. * @@ -2975,13 +2987,13 @@ public TruffleFile getPublicTruffleFile(URI uri) { * * @param path the absolute or relative path to create {@link TruffleFile} for * @return {@link TruffleFile} + * @since 19.3.0 * @throws UnsupportedOperationException when the {@link FileSystem} supports only * {@link URI} * @throws IllegalArgumentException if the {@code path} string cannot be converted to a * {@link Path} * @see #getTruffleFileInternal(String, Predicate) * @see #getPublicTruffleFile(java.lang.String) - * @since 19.3.0 */ @TruffleBoundary public TruffleFile getInternalTruffleFile(String path) { @@ -3002,13 +3014,13 @@ public TruffleFile getInternalTruffleFile(String path) { * * @param uri the {@link URI} to create {@link TruffleFile} for * @return {@link TruffleFile} + * @since 19.3.0 * @throws UnsupportedOperationException when {@link URI} scheme is not supported * @throws IllegalArgumentException if preconditions on the {@code uri} do not hold. * @throws java.nio.file.FileSystemNotFoundException is the file system, identified by the * {@code uri}, does not exist and cannot be created automatically * @see #getTruffleFileInternal(URI, Predicate) * @see #getPublicTruffleFile(java.net.URI) - * @since 19.3.0 */ @TruffleBoundary public TruffleFile getInternalTruffleFile(URI uri) { @@ -3063,10 +3075,11 @@ public TruffleFile getInternalTruffleFile(URI uri) { * {@link URI} * @throws IllegalArgumentException if the {@code path} string cannot be converted to a * {@link Path} + * @since 21.1.0 * @see #getTruffleFileInternal(URI, Predicate) * @see #getPublicTruffleFile(String) * @see #getInternalTruffleFile(String) - * @since 21.1.0 + * */ @TruffleBoundary public TruffleFile getTruffleFileInternal(String path, Predicate filter) { @@ -3087,10 +3100,11 @@ public TruffleFile getTruffleFileInternal(String path, Predicate fi * @throws IllegalArgumentException if preconditions on the {@code uri} do not hold. * @throws java.nio.file.FileSystemNotFoundException is the file system, identified by the * {@code uri}, does not exist and cannot be created automatically + * @since 21.1.0 * @see #getTruffleFileInternal(String, Predicate) * @see #getPublicTruffleFile(URI) * @see #getInternalTruffleFile(URI) - * @since 21.1.0 + * */ @TruffleBoundary public TruffleFile getTruffleFileInternal(URI uri, Predicate filter) { @@ -3505,6 +3519,7 @@ public Object createHostAdapterClassWithStaticOverrides(Class[] types, Object * @throws UnsupportedOperationException if creating adapter classes is not supported on * this runtime at all, which is currently the case for native images. * @throws NullPointerException if {@code types} is null + * * @see #createHostAdapterWithClassOverrides(Object[], Object) * @since 22.1 */ @@ -3546,6 +3561,7 @@ public Object createHostAdapter(Object[] types) { * @throws UnsupportedOperationException if creating adapter classes is not supported on * this runtime at all, which is currently the case for native images. * @throws NullPointerException if either {@code types} or {@code classOverrides} is null. + * * @see #createHostAdapter(Object[]) * @since 22.1 */ @@ -3623,6 +3639,7 @@ public TruffleFile getInternalResource(String resourceId) throws IOException { * empty a root logger for language or instrument is returned * @return a {@link TruffleLogger} * @since 21.1 + * */ @TruffleBoundary public TruffleLogger getLogger(String loggerName) { @@ -3783,7 +3800,8 @@ public SandboxPolicy getSandboxPolicy() { *

    * Languages should check for {@link #isPolyglotEvalAllowed(LanguageInfo) eval permissions} * for each {@link #getPublicLanguages() public language} prior to calling this method, - * otherwise it might cause an internal error if not sufficient privileges are available. + * otherwise it might cause {@link SecurityException} if not sufficient privileges are + * available. * * @return the scope, or null if the requested language does not support such a * concept @@ -3972,7 +3990,7 @@ static RuntimeException engineToLanguageException(T * current {@link Node}, if available, as parameter. *

    * Example intended usage: - *

    + * * See {@link ContextReference} for a full usage example. * * @since 0.25 revised in 21.3 @@ -4264,14 +4282,15 @@ public enum ContextPolicy { /** * Mode of exit operation. * - * @see #exitContext(Object, ExitMode, int) * @since 22.0 + * @see #exitContext(Object, ExitMode, int) */ public enum ExitMode { /** * Natural exit that occurs during normal context close. * * @since 22.0 + * */ NATURAL, /** diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguageContext.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguageContext.java index 90d1b327630b..7197093cabbd 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguageContext.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotLanguageContext.java @@ -242,30 +242,13 @@ boolean isPolyglotBindingsAccessAllowed() { } boolean isPolyglotEvalAllowed(LanguageInfo info) { - Map> allAccess = getAPIAccess().getEvalAccess(context.config.polyglotAccess); - if (allAccess != null && allAccess.size() == 0) { + Set languageAccess = getAPIAccess().getEvalAccess(context.config.polyglotAccess, language.getId()); + if (languageAccess != null && languageAccess.isEmpty()) { return false; } - Set languageAccess = null; - if (allAccess != null) { - languageAccess = allAccess.get(language.getId()); - if (languageAccess != null && languageAccess.size() == 0) { - return false; - } - } - - if (languageAccess == null && allAccess != null && allAccess.size() != 0) { - // there are other languages configured but this language has no access. - return false; - } - if (info == null) { return true; } else { - if (languageAccess != null && !info.getId().equals(language.getId()) && !languageAccess.contains(info.getId())) { - // check whether the target language is included - return false; - } return getAccessibleLanguages(false).containsKey(info.getId()); } } From eea4486f689f2d2abc2f262ad027ab511b04cc13 Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Thu, 30 May 2024 12:59:24 +0200 Subject: [PATCH 6/7] Fixed gates. --- .../src/org/graalvm/polyglot/PolyglotAccess.java | 2 +- truffle/src/com.oracle.truffle.api/snapshot.sigtest | 4 ++++ .../src/com/oracle/truffle/api/TruffleLanguage.java | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/PolyglotAccess.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/PolyglotAccess.java index 5b440bf3f38f..3063c1ea8ce2 100644 --- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/PolyglotAccess.java +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/PolyglotAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 diff --git a/truffle/src/com.oracle.truffle.api/snapshot.sigtest b/truffle/src/com.oracle.truffle.api/snapshot.sigtest index 527fdbe3f34a..26a2e8d14b0f 100644 --- a/truffle/src/com.oracle.truffle.api/snapshot.sigtest +++ b/truffle/src/com.oracle.truffle.api/snapshot.sigtest @@ -543,6 +543,8 @@ meth public boolean isMimeTypeSupported(java.lang.String) meth public boolean isNativeAccessAllowed() meth public boolean isPolyglotBindingsAccessAllowed() meth public boolean isPolyglotEvalAllowed() + anno 0 java.lang.Deprecated(boolean forRemoval=false, java.lang.String since="") +meth public boolean isPolyglotEvalAllowed(com.oracle.truffle.api.nodes.LanguageInfo) meth public boolean isPreInitialization() meth public boolean isSocketIOAllowed() meth public com.oracle.truffle.api.TruffleContext getContext() @@ -575,6 +577,8 @@ meth public java.lang.Object createHostAdapterClassWithStaticOverrides(java.lang meth public java.lang.Object createHostAdapterWithClassOverrides(java.lang.Object[],java.lang.Object) meth public java.lang.Object findMetaObject(java.lang.Object) meth public java.lang.Object getPolyglotBindings() +meth public java.lang.Object getScopeInternal(com.oracle.truffle.api.nodes.LanguageInfo) +meth public java.lang.Object getScopePublic(com.oracle.truffle.api.nodes.LanguageInfo) meth public java.lang.Object importSymbol(java.lang.String) meth public java.lang.Object lookupHostSymbol(java.lang.String) meth public java.lang.String getFileNameSeparator() diff --git a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java index 3dd2f1aa7711..bdce631d1367 100644 --- a/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java +++ b/truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java @@ -2505,8 +2505,8 @@ public boolean isPolyglotEvalAllowed() { * The result of this method is safe to be cached per language context, it is guaranteed to * not change for a context and target language combination. * - * @see PolyglotAccess.Builder#allowEval(String, String) Embedders can restrict polyglot - * eval access between certain languages. + * @see org.graalvm.polyglot.PolyglotAccess.Builder#allowEval(String, String) Embedders can + * restrict polyglot eval access between certain languages. * @see #parsePublic(Source, String...) * @see #getScopePublic(LanguageInfo) * @since 24.1 From 2b1814cc39fd322de14888617704253b2e084f52 Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Mon, 3 Jun 2024 11:00:34 +0200 Subject: [PATCH 7/7] [GR-28866] Resovled review comments. --- .../src/com/oracle/truffle/polyglot/EngineAccessor.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java index 396ef76ad74a..76e766d3f7f3 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/EngineAccessor.java @@ -506,13 +506,13 @@ public TruffleLanguage.Env getEnvForInstrument(LanguageInfo info) { @Override public Object getScope(Object polyglotLanguageContext, LanguageInfo requiredLanguage, boolean internal) { PolyglotLanguageContext languageContext = (PolyglotLanguageContext) polyglotLanguageContext; - boolean allowed; + Map allowedLanguages; if (internal) { - allowed = getInternalLanguages(languageContext).containsKey(requiredLanguage.getId()); + allowedLanguages = getInternalLanguages(languageContext); } else { - allowed = getPublicLanguages(languageContext).containsKey(requiredLanguage.getId()); + allowedLanguages = getPublicLanguages(languageContext); } - if (!allowed) { + if (!allowedLanguages.containsKey(requiredLanguage.getId())) { throw new PolyglotEngineException(new SecurityException(String.format("Access to language '%s' is not permitted.", requiredLanguage.getId()))); } PolyglotContextImpl context = languageContext.context;