Skip to content

Commit c7d098f

Browse files
committed
latest core-js scope handling
1 parent 6b12bea commit c7d098f

21 files changed

+112
-87
lines changed

src/main/java/org/htmlunit/WebWindow.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import java.io.Serializable;
1818

19+
import org.htmlunit.corejs.javascript.TopLevel;
1920
import org.htmlunit.css.ComputedCssStyleDeclaration;
2021
import org.htmlunit.html.DomElement;
2122
import org.htmlunit.javascript.HtmlUnitScriptable;
@@ -75,6 +76,9 @@ public interface WebWindow extends Serializable {
7576
*/
7677
WebWindow getTopWindow();
7778

79+
TopLevel getTopLevelScope();
80+
void setTopLevelScope(TopLevel topLevelScope);
81+
7882
/**
7983
* Returns the web client that "owns" this window.
8084
*

src/main/java/org/htmlunit/WebWindowImpl.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import org.apache.commons.logging.Log;
2929
import org.apache.commons.logging.LogFactory;
30+
import org.htmlunit.corejs.javascript.TopLevel;
3031
import org.htmlunit.css.ComputedCssStyleDeclaration;
3132
import org.htmlunit.css.CssStyleSheet;
3233
import org.htmlunit.css.ElementCssStyleDeclaration;
@@ -59,6 +60,7 @@ public abstract class WebWindowImpl implements WebWindow {
5960
private final Screen screen_;
6061
private Page enclosedPage_;
6162
private transient HtmlUnitScriptable scriptObject_;
63+
private transient TopLevel topLevelScope_;
6264
private JavaScriptJobManager jobManager_;
6365
private final List<WebWindowImpl> childWindows_ = new ArrayList<>();
6466
private String name_ = "";
@@ -184,6 +186,22 @@ public <T> T getScriptableObject() {
184186
return (T) scriptObject_;
185187
}
186188

189+
/**
190+
* {@inheritDoc}
191+
*/
192+
@Override
193+
public void setTopLevelScope(final TopLevel topLevelScope) {
194+
topLevelScope_ = topLevelScope;
195+
}
196+
197+
/**
198+
* {@inheritDoc}
199+
*/
200+
@Override
201+
public TopLevel getTopLevelScope() {
202+
return topLevelScope_;
203+
}
204+
187205
/**
188206
* {@inheritDoc}
189207
*/

src/main/java/org/htmlunit/html/HtmlPage.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -948,7 +948,7 @@ public ScriptResult executeJavaScript(String sourceCode, final String sourceName
948948
}
949949

950950
final Object result = getWebClient().getJavaScriptEngine()
951-
.execute(this, getEnclosingWindow().getScriptableObject(), sourceCode, sourceName, startLine);
951+
.execute(this, getEnclosingWindow().getTopLevelScope(), sourceCode, sourceName, startLine);
952952
return new ScriptResult(result);
953953
}
954954

src/main/java/org/htmlunit/javascript/HtmlUnitScriptable.java

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.htmlunit.corejs.javascript.NativePromise;
3434
import org.htmlunit.corejs.javascript.Scriptable;
3535
import org.htmlunit.corejs.javascript.ScriptableObject;
36+
import org.htmlunit.corejs.javascript.TopLevel;
3637
import org.htmlunit.html.DomNode;
3738
import org.htmlunit.html.HtmlImage;
3839
import org.htmlunit.javascript.host.Window;
@@ -96,6 +97,9 @@ public void setParentScope(final Scriptable scope) {
9697
if (scope == this) {
9798
throw new IllegalArgumentException("Object can't be its own parentScope");
9899
}
100+
if (scope instanceof Window) {
101+
throw new IllegalArgumentException("parentScope can't be the window");
102+
}
99103
super.setParentScope(scope);
100104
}
101105

@@ -279,13 +283,7 @@ else if (domNode.hasFeature(HTMLIMAGE_HTMLUNKNOWNELEMENT)) {
279283
*/
280284
protected void initParentScope(final DomNode domNode, final HtmlUnitScriptable scriptable) {
281285
final SgmlPage page = domNode.getPage();
282-
final WebWindow enclosingWindow = page.getEnclosingWindow();
283-
if (enclosingWindow != null && enclosingWindow.getEnclosedPage() == page) {
284-
scriptable.setParentScope(enclosingWindow.getScriptableObject());
285-
}
286-
else {
287-
scriptable.setParentScope(ScriptableObject.getTopLevelScope(page.getScriptableObject()));
288-
}
286+
scriptable.setParentScope(ScriptableObject.getTopLevelScope(page.getScriptableObject()));
289287
}
290288

291289
/**
@@ -332,8 +330,12 @@ public Window getWindow() throws RuntimeException {
332330
* @throws RuntimeException if the window cannot be found, which should never occur
333331
*/
334332
protected static Window getWindow(final Scriptable s) throws RuntimeException {
335-
final Scriptable top = ScriptableObject.getTopLevelScope(s);
336-
if (top instanceof Window window) {
333+
if (s instanceof Window window) {
334+
return window;
335+
}
336+
337+
final TopLevel topLevel = ScriptableObject.getTopLevelScope(s);
338+
if (topLevel.getGlobalThis() instanceof Window window) {
337339
return window;
338340
}
339341
throw new RuntimeException("Unable to find window associated with " + s);
@@ -346,8 +348,11 @@ protected static Window getWindow(final Scriptable s) throws RuntimeException {
346348
*/
347349
protected static Window getWindowFromTopCallScope() throws RuntimeException {
348350
final Scriptable top = JavaScriptEngine.getTopCallScope();
349-
if (top instanceof Window window) {
350-
return window;
351+
if (top instanceof TopLevel topLevel) {
352+
final ScriptableObject globalThis = topLevel.getGlobalThis();
353+
if (globalThis instanceof Window window) {
354+
return window;
355+
}
351356
}
352357
throw new RuntimeException("Unable to find window in scope");
353358
}

src/main/java/org/htmlunit/javascript/JavaScriptEngine.java

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,8 @@ private void init(final WebWindow webWindow, final Page page, final Context cx)
211211
final Window jsWindow = new Window();
212212
jsWindow.setClassName("Window");
213213

214-
final Scriptable scope = cx.initSafeStandardObjects(jsWindow);
214+
final TopLevel scope = cx.initSafeStandardObjects(new TopLevel(jsWindow));
215+
jsWindow.setParentScope(scope);
215216
configureRhino(webClient, browserVersion, scope, jsWindow);
216217

217218
final Map<Class<? extends Scriptable>, Scriptable> prototypes = new HashMap<>();
@@ -232,8 +233,8 @@ private void init(final WebWindow webWindow, final Page page, final Context cx)
232233
configureGlobalThis(scope, jsWindow, windowConfig, functionObject, jsConfig_, browserVersion, prototypes, prototypesPerJSName);
233234

234235
// TODO remove the cast
235-
URLSearchParams.NativeParamsIterator.init((ScriptableObject) scope, "URLSearchParams Iterator");
236-
FormData.FormDataIterator.init((ScriptableObject) scope, "FormData Iterator");
236+
URLSearchParams.NativeParamsIterator.init(scope, "URLSearchParams Iterator");
237+
FormData.FormDataIterator.init(scope, "FormData Iterator");
237238

238239
// strange but this is the reality for browsers
239240
// because there will be still some sites using this for browser detection the property is
@@ -275,7 +276,7 @@ private void init(final WebWindow webWindow, final Page page, final Context cx)
275276
* @throws Exception in case of error
276277
*/
277278
public static void configureGlobalThis(
278-
final Scriptable scope,
279+
final TopLevel scope,
279280
final HtmlUnitScriptable globalThis,
280281
final ClassConfiguration scopeConfig,
281282
final FunctionObject scopeContructorFunctionObject,
@@ -414,17 +415,17 @@ private static void additionalCtor(final Scriptable scope, final Window window,
414415
* @param globalThis the window or the DedicatedWorkerGlobalScope
415416
*/
416417
public static void configureRhino(final WebClient webClient, final BrowserVersion browserVersion,
417-
final Scriptable scope, final HtmlUnitScriptable globalThis) {
418+
final TopLevel scope, final HtmlUnitScriptable globalThis) {
418419

419420
// this should be like
420421
// NativeConsole.init(scope, globalThis, false, webClient.getWebConsole());
421422
// but so far both objects are the same
422-
NativeConsole.init(globalThis, false, webClient.getWebConsole());
423+
NativeConsole.init(scope, false, webClient.getWebConsole());
423424

424425
// https://developer.mozilla.org/en-US/docs/Web/API/console/timeStamp_static
425426
// this is not standard and therefore not in Rhino
426427
final ScriptableObject console = (ScriptableObject) ScriptableObject.getProperty(globalThis, "console");
427-
console.defineFunctionProperties(new String[] {"timeStamp"}, ConsoleCustom.class, ScriptableObject.DONTENUM);
428+
console.defineFunctionProperties(scope, new String[] {"timeStamp"}, ConsoleCustom.class, ScriptableObject.DONTENUM);
428429

429430
// remove some objects, that Rhino defines in top scope but that we don't want
430431
deleteProperties(globalThis, "Continuation", "StopIteration", "uneval", "global");
@@ -543,7 +544,7 @@ private static void removePrototypeProperties(final Scriptable scope, final Stri
543544
* @throws Exception in case of errors
544545
*/
545546
public static HtmlUnitScriptable configureClass(final ClassConfiguration config,
546-
final Scriptable scope)
547+
final TopLevel scope)
547548
throws Exception {
548549

549550
final HtmlUnitScriptable prototype = config.getHostClass().getDeclaredConstructor().newInstance();
@@ -561,7 +562,7 @@ public static HtmlUnitScriptable configureClass(final ClassConfiguration config,
561562
* @param scriptable the object to configure
562563
*/
563564
private static void configureConstantsStaticPropertiesAndStaticFunctions(final ClassConfiguration config,
564-
final Scriptable scope, final ScriptableObject scriptable) {
565+
final TopLevel scope, final ScriptableObject scriptable) {
565566
configureConstants(config, scriptable);
566567
configureStaticProperties(config, scope, scriptable);
567568
configureStaticFunctions(config, scope, scriptable);
@@ -574,7 +575,7 @@ private static void configureConstantsStaticPropertiesAndStaticFunctions(final C
574575
* @param scriptable the object to configure
575576
*/
576577
private static void configureConstantsPropertiesAndFunctions(final ClassConfiguration config,
577-
final Scriptable scope, final ScriptableObject scriptable) {
578+
final TopLevel scope, final ScriptableObject scriptable) {
578579
configureConstants(config, scriptable);
579580
configureProperties(config, scope, scriptable);
580581
configureFunctions(config, scope, scriptable);
@@ -583,7 +584,7 @@ private static void configureConstantsPropertiesAndFunctions(final ClassConfigur
583584
}
584585

585586
private static void configureFunctions(final ClassConfiguration config,
586-
final Scriptable scope, final ScriptableObject scriptable) {
587+
final TopLevel scope, final ScriptableObject scriptable) {
587588
// the functions
588589
final Map<String, Method> functionMap = config.getFunctionMap();
589590
if (functionMap != null) {
@@ -606,20 +607,20 @@ private static void configureConstants(final ClassConfiguration config, final Sc
606607
}
607608

608609
private static void configureProperties(final ClassConfiguration config,
609-
final Scriptable scope, final ScriptableObject scriptable) {
610+
final TopLevel scope, final ScriptableObject scriptable) {
610611
final Map<String, PropertyInfo> propertyMap = config.getPropertyMap();
611612
if (propertyMap != null) {
612613
for (final Entry<String, PropertyInfo> propertyEntry : propertyMap.entrySet()) {
613614
final PropertyInfo info = propertyEntry.getValue();
614615
final Method readMethod = info.getReadMethod();
615616
final Method writeMethod = info.getWriteMethod();
616-
scriptable.defineProperty(propertyEntry.getKey(), null, readMethod, writeMethod, ScriptableObject.EMPTY);
617+
scriptable.defineProperty(scope, propertyEntry.getKey(), null, readMethod, writeMethod, ScriptableObject.EMPTY);
617618
}
618619
}
619620
}
620621

621622
private static void configureStaticProperties(final ClassConfiguration config,
622-
final Scriptable scope, final ScriptableObject scriptable) {
623+
final TopLevel scope, final ScriptableObject scriptable) {
623624
final Map<String, PropertyInfo> staticPropertyMap = config.getStaticPropertyMap();
624625
if (staticPropertyMap != null) {
625626
for (final Entry<String, ClassConfiguration.PropertyInfo> propertyEntry : staticPropertyMap.entrySet()) {
@@ -628,13 +629,13 @@ private static void configureStaticProperties(final ClassConfiguration config,
628629
final Method writeMethod = propertyEntry.getValue().getWriteMethod();
629630
final int flag = ScriptableObject.EMPTY;
630631

631-
scriptable.defineProperty(propertyName, null, readMethod, writeMethod, flag);
632+
scriptable.defineProperty(scope, propertyName, null, readMethod, writeMethod, flag);
632633
}
633634
}
634635
}
635636

636637
private static void configureStaticFunctions(final ClassConfiguration config,
637-
final Scriptable scope, final ScriptableObject scriptable) {
638+
final TopLevel scope, final ScriptableObject scriptable) {
638639
final Map<String, Method> staticFunctionMap = config.getStaticFunctionMap();
639640
if (staticFunctionMap != null) {
640641
for (final Entry<String, Method> staticFunctionInfo : staticFunctionMap.entrySet()) {
@@ -656,7 +657,7 @@ private static void configureSymbolConstants(final ClassConfiguration config, fi
656657
}
657658

658659
private static void configureSymbols(final ClassConfiguration config,
659-
final Scriptable scope, final ScriptableObject scriptable) {
660+
final TopLevel scope, final ScriptableObject scriptable) {
660661
final Map<Symbol, Method> symbolMap = config.getSymbolMap();
661662
if (symbolMap != null) {
662663
for (final Entry<Symbol, Method> symbolInfo : symbolMap.entrySet()) {
@@ -791,7 +792,7 @@ public Object execute(final HtmlPage page, final Scriptable scope, final Script
791792
final HtmlUnitContextAction action = new HtmlUnitContextAction(page) {
792793
@Override
793794
public Object doRun(final Context cx) {
794-
return script.exec(cx, scope, scope);
795+
return script.exec(cx, scope, ((TopLevel) scope).getGlobalThis());
795796
}
796797

797798
@Override
@@ -1259,15 +1260,15 @@ public static EcmaError constructError(final String error, final String message)
12591260
*
12601261
* Creates a {@link DOMException} and encapsulates it into a Rhino-compatible exception.
12611262
*
1262-
* @param scope the parent scope
1263+
* @param scriptable the scriptable triggering this
12631264
* @param message the exception message
12641265
* @param type the exception type
12651266
* @return the created exception
12661267
*/
1267-
public static RhinoException asJavaScriptException(final HtmlUnitScriptable scope, final String message, final int type) {
1268+
public static RhinoException asJavaScriptException(final HtmlUnitScriptable scriptable, final String message, final int type) {
12681269
final DOMException domException = new DOMException(message, type);
1269-
domException.setParentScope(scope);
1270-
domException.setPrototype(scope.getPrototype(DOMException.class));
1270+
domException.setParentScope(scriptable.getParentScope());
1271+
domException.setPrototype(scriptable.getWindow().getPrototype(DOMException.class));
12711272

12721273
final EcmaError helper = ScriptRuntime.syntaxError("helper");
12731274
String fileName = helper.sourceName();
@@ -1480,7 +1481,7 @@ public static String evaluateProxyAutoConfig(final BrowserVersion browserVersion
14801481
ProxyAutoConfigJavaScriptConfiguration.getInstance(browserVersion);
14811482

14821483
final ScriptableObject globalThis = new NativeObject();
1483-
final Scriptable scope = cx.initSafeStandardObjects(globalThis);
1484+
final TopLevel scope = cx.initSafeStandardObjects(new TopLevel(globalThis));
14841485

14851486
for (final ClassConfiguration config : jsConfig.getAll()) {
14861487
configureFunctions(config, scope, globalThis);

src/main/java/org/htmlunit/javascript/host/Element.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1611,7 +1611,7 @@ public static boolean matches(final Context context, final Scriptable scope,
16111611
}
16121612
catch (final CSSException e) {
16131613
throw JavaScriptEngine.asJavaScriptException(
1614-
(HtmlUnitScriptable) getTopLevelScope(thisObj),
1614+
(HtmlUnitScriptable) getTopLevelScope(thisObj).getGlobalThis(),
16151615
"An invalid or illegal selector was specified (selector: '"
16161616
+ selectorString + "' error: " + e.getMessage() + ").",
16171617
DOMException.SYNTAX_ERR);

src/main/java/org/htmlunit/javascript/host/Location.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -192,15 +192,15 @@ public void initialize(final Scriptable scope, final Window window, final Page p
192192
functionObject = new FunctionObject(METHOD_TO_STRING.getName(), METHOD_TO_STRING, this);
193193
defineProperty("toString", functionObject, attributes);
194194

195-
defineProperty("hash", null, GETTER_HASH, SETTER_HASH, attributes);
196-
defineProperty("host", null, GETTER_HOST, SETTER_HOST, attributes);
197-
defineProperty("hostname", null, GETTER_HOSTNAME, SETTER_HOSTNAME, attributes);
198-
defineProperty("href", null, GETTER_HREF, SETTER_HREF, attributes);
199-
defineProperty("origin", null, GETTER_ORIGIN, null, attributes);
200-
defineProperty("pathname", null, GETTER_PATHNAME, SETTER_PATHNAME, attributes);
201-
defineProperty("port", null, GETTER_PORT, SETTER_PORT, attributes);
202-
defineProperty("protocol", null, GETTER_PROTOCOL, SETTER_PROTOCOL, attributes);
203-
defineProperty("search", null, GETTER_SEARCH, SETTER_SEARCH, attributes);
195+
defineProperty(scope, "hash", null, GETTER_HASH, SETTER_HASH, attributes);
196+
defineProperty(scope, "host", null, GETTER_HOST, SETTER_HOST, attributes);
197+
defineProperty(scope, "hostname", null, GETTER_HOSTNAME, SETTER_HOSTNAME, attributes);
198+
defineProperty(scope, "href", null, GETTER_HREF, SETTER_HREF, attributes);
199+
defineProperty(scope, "origin", null, GETTER_ORIGIN, null, attributes);
200+
defineProperty(scope, "pathname", null, GETTER_PATHNAME, SETTER_PATHNAME, attributes);
201+
defineProperty(scope, "port", null, GETTER_PORT, SETTER_PORT, attributes);
202+
defineProperty(scope, "protocol", null, GETTER_PROTOCOL, SETTER_PROTOCOL, attributes);
203+
defineProperty(scope, "search", null, GETTER_SEARCH, SETTER_SEARCH, attributes);
204204

205205
window_ = window;
206206
if (window_ != null && page != null) {

src/main/java/org/htmlunit/javascript/host/Storage.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public Storage(final Window window, final Map<String, String> store) {
7575
super();
7676
store_ = store;
7777
storeSize_ = 0L;
78-
setParentScope(window);
78+
setParentScope(window.getWebWindow().getTopLevelScope());
7979
setPrototype(window.getPrototype(Storage.class));
8080
}
8181

src/main/java/org/htmlunit/javascript/host/URLSearchParams.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@
3535
import org.htmlunit.corejs.javascript.NativeObject;
3636
import org.htmlunit.corejs.javascript.ScriptRuntime;
3737
import org.htmlunit.corejs.javascript.Scriptable;
38-
import org.htmlunit.corejs.javascript.ScriptableObject;
3938
import org.htmlunit.corejs.javascript.SymbolKey;
39+
import org.htmlunit.corejs.javascript.TopLevel;
4040
import org.htmlunit.javascript.HtmlUnitScriptable;
4141
import org.htmlunit.javascript.JavaScriptEngine;
4242
import org.htmlunit.javascript.configuration.JsxClass;
@@ -81,7 +81,7 @@ enum Type { KEYS, VALUES, BOTH }
8181
* @param scope the scope
8282
* @param className the class name
8383
*/
84-
public static void init(final ScriptableObject scope, final String className) {
84+
public static void init(final TopLevel scope, final String className) {
8585
ES6Iterator.init(scope, false, new NativeParamsIterator(className), URL_SEARCH_PARMS_TAG);
8686
}
8787

0 commit comments

Comments
 (0)