3636import org .htmlunit .corejs .javascript .Script ;
3737import org .htmlunit .corejs .javascript .ScriptRuntime ;
3838import org .htmlunit .corejs .javascript .ScriptStackElement ;
39+ import org .htmlunit .corejs .javascript .ScriptableObject ;
3940import org .htmlunit .corejs .javascript .VarScope ;
4041import org .htmlunit .corejs .javascript .debug .Debugger ;
4142import org .htmlunit .html .ContentSecurityPolicy ;
4243import org .htmlunit .html .HtmlElement ;
4344import org .htmlunit .html .HtmlPage ;
45+ import org .htmlunit .javascript .host .Window ;
4446
4547/**
4648 * ContextFactory that supports termination of scripts if they exceed a timeout. Based on example from
@@ -166,10 +168,6 @@ protected Script compileString(String source, final Evaluator compiler,
166168 // which is used for window.eval. We have to take care in which case we are.
167169 final boolean isWindowEval = compiler != null ;
168170
169- if (isWindowEval ) {
170- ensureEvalAllowed (source );
171- }
172-
173171 // Remove HTML comments around the source if needed
174172 if (!isWindowEval ) {
175173
@@ -203,16 +201,20 @@ protected Script compileString(String source, final Evaluator compiler,
203201 sourceName , lineno , securityDomain , compilerEnvironsProcessor );
204202 }
205203
204+ /**
205+ * Like the browsers, checks the Content-Security-Policy of the realm (page) the
206+ * string is compiled for (eval, new Function()).
207+ */
208+ @ Override
209+ protected void ensureCanCompileStrings (final VarScope scope , final String source ) {
210+ ensureEvalAllowed (source , scope );
211+ }
212+
206213 @ Override
207214 protected Function compileFunction (final VarScope scope , String source ,
208215 final Evaluator compiler , final ErrorReporter compilationErrorReporter ,
209216 final String sourceName , final int lineno , final Object securityDomain ) {
210217
211- // the compiler is only given for new Function(...)
212- if (compiler != null ) {
213- ensureEvalAllowed (source );
214- }
215-
216218 if (deminifyFunctionCode_ ) {
217219 final Function f = super .compileFunction (scope , source , compiler ,
218220 compilationErrorReporter , sourceName , lineno , securityDomain );
@@ -224,18 +226,29 @@ protected Function compileFunction(final VarScope scope, String source,
224226 }
225227
226228 /**
227- * Throws an EvalError if the Content-Security-Policy of the page of the
228- * running script does not allow the evaluation of strings as code.
229+ * Throws an EvalError if the Content-Security-Policy of the page
230+ * does not allow the evaluation of strings as code.
231+ * Like the browsers, the policy of the realm of the called function is used (e.g. for
232+ * {@code frame.contentWindow.eval(...)} or {@code new frame.contentWindow.Function(...)} the
233+ * policy of the frame); if the realm has no page the page of the running script is used.
229234 *
230235 * @param source the source to evaluate
236+ * @param scope the scope of the realm
231237 */
232- private static void ensureEvalAllowed (final String source ) {
238+ private static void ensureEvalAllowed (final String source , final VarScope scope ) {
233239 final Context cx = Context .getCurrentContext ();
234240 if (cx == null ) {
235241 return ;
236242 }
237243
238- Object page = cx .getThreadLocal (JavaScriptEngine .KEY_RUNNING_PAGE );
244+ Object page = null ;
245+ if (scope != null
246+ && ScriptableObject .getTopLevelScope (scope ).getGlobalThis () instanceof Window window ) {
247+ page = window .getWebWindow ().getEnclosedPage ();
248+ }
249+ if (!(page instanceof HtmlPage )) {
250+ page = cx .getThreadLocal (JavaScriptEngine .KEY_RUNNING_PAGE );
251+ }
239252 if (!(page instanceof HtmlPage )) {
240253 page = cx .getThreadLocal (JavaScriptEngine .KEY_STARTING_PAGE );
241254 }
0 commit comments