@@ -96,82 +96,88 @@ private static JSServiceArgs args(Path pluginPath, Optional<MongoClient> mclient
9696 LOGGER .trace ("Enabling require for service {} with require-cwd {} " , pluginPath , requireCwdPath );
9797 }
9898
99- var ctx = ContextQueue .newContext (engine (), "foo" , config , LOGGER , mclient , "" , contextOptions );
99+ // Context creation, eval and all Value member access must happen on the very
100+ // same platform thread: a Value returned by eval() is only safely readable on
101+ // the thread the context is entered on (see PolyglotThreadUtils), so the whole
102+ // block below -- not just the eval() calls -- is dispatched as a single task.
100103 try {
101- // check that the plugin script is js (use PluginsClassloader so js-language is visible)
102- final var language = PolyglotClassloaderHelper . withPluginsClassloaderResult (
103- () -> Source . findLanguage ( pluginPath . toFile ()) );
104-
105- if (! "js" . equals ( language )) {
106- throw new IllegalArgumentException ( "wrong js plugin, not javascript" );
107- }
108-
109- var sindexPath = pluginPath . toUri (). toString ();
110- LOGGER . debug ( "Resolved plugin path for import: {}" , sindexPath );
111- var optionsScript = "import { options } from '" + sindexPath + "'; options;" ;
112- var optionsSource = Source . newBuilder ( language , optionsScript , "optionsScript" ). mimeType ( "application/javascript+module" ). build ();
113-
114- Value options ;
115-
116- try {
117- // ctx.eval() touches thread locals, must run on a platform thread, see PolyglotThreadUtils
118- options = PolyglotThreadUtils . onPlatformThread (() -> ctx . eval ( optionsSource )) ;
119- } catch ( Throwable t ) {
120- if ( t . getMessage () != null && t . getMessage (). contains ( "Cannot load CommonJS module" )) {
121- throw new IllegalArgumentException ( "wrong js service " + pluginPath . toAbsolutePath () + ": " + t . getMessage () );
122- } else if ( t . getMessage () != null && t . getMessage (). contains ( "Access to host class" ) ) {
123- throw new IllegalArgumentException ( "wrong js service " + pluginPath . toAbsolutePath () + ": " + t .getMessage ());
124- } else {
125- throw new IllegalArgumentException ( "wrong js service " + pluginPath . toAbsolutePath () + ": " + t .getMessage () + ", " + PACKAGE_HINT );
126- }
127- }
128-
129- checkOptions ( options , pluginPath );
130-
131- var name = options . getMember ( "name" ). asString ();
132- var description = options . getMember ( "description" ). asString ( );
133- var uri = options . getMember ( "uri" ). asString ();
134- var secured = ! options . getMemberKeys (). contains ( "secured" ) ? false : options .getMember ("secured " ).asBoolean ();
135- var matchPolicy = ! options . getMemberKeys (). contains ( "matchPolicy" ) ? MATCH_POLICY . PREFIX : MATCH_POLICY . valueOf ( options .getMember ("matchPolicy " ).asString () );
136- String modulesReplacements = null ;
137-
138- if ( options .getMemberKeys ().contains ("modulesReplacements" )) {
139- var sb = new StringBuilder () ;
140-
141- options .getMember ( "modulesReplacements" ). getMemberKeys ().stream ()
142- . forEach ( k -> sb . append ( k ). append ( ":" )
143- . append ( options . getMember ( "modulesReplacements" ). getMember ( k ))
144- . append ( "," ));
145-
146- modulesReplacements = sb . toString ();
147- }
148-
149- // ******** evaluate and check handle
150- var _handleScript = "import { handle } from '" + sindexPath + "'; handle;" ;
151- var handleSource = Source . newBuilder ( language , _handleScript , "handleScript" ). mimeType ( "application/javascript+module" ). build ();
152-
153- Value handle ;
154-
155- try {
156- // ctx.eval() touches thread locals, must run on a platform thread, see PolyglotThreadUtils
157- handle = PolyglotThreadUtils . onPlatformThread (() -> ctx . eval ( handleSource ));
158- } catch ( Throwable t ) {
159- throw new IllegalArgumentException ( "wrong js service " + pluginPath . toAbsolutePath () + ", " + t . getMessage () );
160- }
161-
162- checkHandle ( handle , pluginPath );
163-
164- return new JSServiceArgs ( name , description , uri , secured , modulesReplacements , matchPolicy , handleSource , config , mclient , contextOptions );
165- } finally {
166- try {
167- // Context.close() touches thread locals, must run on a platform thread, see PolyglotThreadUtils
168- PolyglotThreadUtils . onPlatformThread (() -> {
104+ return PolyglotThreadUtils . onPlatformThread (() -> {
105+ var ctx = ContextQueue . newContext ( engine (), "foo" , config , LOGGER , mclient , "" , contextOptions );
106+ ctx . enter ( );
107+ try {
108+ // check that the plugin script is js (use PluginsClassloader so js- language is visible)
109+ final var language = PolyglotClassloaderHelper . withPluginsClassloaderResult (
110+ () -> Source . findLanguage ( pluginPath . toFile ()));
111+
112+ if (! "js" . equals ( language )) {
113+ throw new IllegalArgumentException ( "wrong js plugin, not javascript" );
114+ }
115+
116+ var sindexPath = pluginPath . toUri (). toString ();
117+ LOGGER . debug ( "Resolved plugin path for import: {}" , sindexPath ) ;
118+ var optionsScript = "import { options } from '" + sindexPath + "'; options;" ;
119+ var optionsSource = Source . newBuilder ( language , optionsScript , "optionsScript" ). mimeType ( "application/javascript+module" ). build ();
120+
121+ Value options ;
122+
123+ try {
124+ options = ctx . eval ( optionsSource );
125+ } catch ( Throwable t ) {
126+ if ( t . getMessage () != null && t .getMessage (). contains ( "Cannot load CommonJS module" )) {
127+ throw new IllegalArgumentException ( "wrong js service " + pluginPath . toAbsolutePath () + ": " + t . getMessage ());
128+ } else if ( t . getMessage () != null && t .getMessage (). contains ( "Access to host class" )) {
129+ throw new IllegalArgumentException ( "wrong js service " + pluginPath . toAbsolutePath () + ": " + t . getMessage ());
130+ } else {
131+ throw new IllegalArgumentException ( "wrong js service " + pluginPath . toAbsolutePath () + ": " + t . getMessage () + ", " + PACKAGE_HINT );
132+ }
133+ }
134+
135+ checkOptions ( options , pluginPath );
136+
137+ var name = options .getMember ("name " ).asString ();
138+ var description = options .getMember ("description " ).asString ();
139+ var uri = options . getMember ( "uri" ). asString () ;
140+ var secured = ! options . getMemberKeys (). contains ( "secured" ) ? false : options . getMember ( "secured" ). asBoolean ();
141+ var matchPolicy = ! options .getMemberKeys ().contains ("matchPolicy" ) ? MATCH_POLICY . PREFIX : MATCH_POLICY . valueOf ( options . getMember ( "matchPolicy" ). asString ());
142+ String modulesReplacements = null ;
143+
144+ if ( options .getMemberKeys ().contains ( "modulesReplacements" )) {
145+ var sb = new StringBuilder ();
146+
147+ options . getMember ( "modulesReplacements" ). getMemberKeys (). stream ()
148+ . forEach ( k -> sb . append ( k ). append ( ":" )
149+ . append ( options . getMember ( "modulesReplacements" ). getMember ( k ))
150+ . append ( "," ));
151+
152+ modulesReplacements = sb . toString ();
153+ }
154+
155+ // ******** evaluate and check handle
156+ var _handleScript = "import { handle } from '" + sindexPath + "'; handle;" ;
157+ var handleSource = Source . newBuilder ( language , _handleScript , "handleScript" ). mimeType ( "application/javascript+module" ). build ();
158+
159+ Value handle ;
160+
161+ try {
162+ handle = ctx . eval ( handleSource );
163+ } catch ( Throwable t ) {
164+ throw new IllegalArgumentException ( "wrong js service " + pluginPath . toAbsolutePath () + ", " + t . getMessage ());
165+ }
166+
167+ checkHandle ( handle , pluginPath );
168+
169+ return new JSServiceArgs ( name , description , uri , secured , modulesReplacements , matchPolicy , handleSource , config , mclient , contextOptions );
170+ } finally {
171+ ctx . leave ();
169172 ctx .close ();
170- return null ;
171- });
172- } catch (Exception e ) {
173- LOGGER .warn ("Error closing context for {}" , pluginPath , e );
174- }
173+ }
174+ });
175+ } catch (RuntimeException re ) {
176+ throw re ;
177+ } catch (IOException ioe ) {
178+ throw ioe ;
179+ } catch (Exception e ) {
180+ throw new IllegalStateException ("Error evaluating js service " + pluginPath .toAbsolutePath (), e );
175181 }
176182 }
177183
0 commit comments