Skip to content

Commit 48f3139

Browse files
committed
core-js updated
1 parent 03748f5 commit 48f3139

3 files changed

Lines changed: 205 additions & 1 deletion

File tree

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242

4343
<htmlunit-csp.version>5.3.0</htmlunit-csp.version>
4444
<htmlunit-cssparser.version>5.3.0</htmlunit-cssparser.version>
45-
<htmlunit-corejs.version>5.3.0</htmlunit-corejs.version>
45+
<htmlunit-corejs.version>5.4.0-SNAPSHOT</htmlunit-corejs.version>
4646
<htmlunit-neko.version>5.3.0</htmlunit-neko.version>
4747
<htmlunit-websocketclient.version>5.3.0</htmlunit-websocketclient.version>
4848
<htmlunit-xpath.version>5.3.0</htmlunit-xpath.version>

src/changes/changes.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@
88

99
<body>
1010
<release version="5.4.0" date="August xx, 2026" description="Chrome/Edge 150, Bugfixes">
11+
<action type="update" dev="rbri" due-to="Lai Quang Duong">
12+
core-js: support for a common workaround for subclassing built-in objects (like Set) without
13+
using ES6 class/extends syntax, by using Reflect.construct() with a newTarget argument added.
14+
</action>
15+
<action type="update" dev="rhino">
16+
core-js: Improved strict mode handling for direct eval calls.
17+
</action>
1118
<action type="update" dev="rbri">
1219
Range.getClientRects() and Range.getBoundingClientRect() ignoring whitespace-only text nodes
1320
and block-level siblings when calculating the horizontal offset of a text node.

src/test/java/org/htmlunit/javascript/NativeReflectTest.java

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,11 @@ public void defineOwnPropertyOutOfBoundsWriteIsDiscarded() throws Exception {
467467
loadPageVerifyTitle2(html);
468468
}
469469

470+
/**
471+
* Test common workaround for subclassing built-in objects (like Set) without using ES6
472+
* class/extends syntax, by using Reflect.construct() with a newTarget argument.
473+
* @throws Exception if the test fails
474+
*/
470475
@Test
471476
@Alerts({"1,2,3,4", "true", "true", "true"})
472477
public void constructSubclassBuiltin() throws Exception {
@@ -491,4 +496,196 @@ public void constructSubclassBuiltin() throws Exception {
491496

492497
loadPageVerifyTitle2(html);
493498
}
499+
500+
/**
501+
* Test common workaround for subclassing built-in objects (like Map) without using ES6
502+
* class/extends syntax, by using Reflect.construct() with a newTarget argument.
503+
* @throws Exception if the test fails
504+
*/
505+
@Test
506+
@Alerts({"a,b,c", "true", "true", "true"})
507+
public void constructSubclassBuiltinMap() throws Exception {
508+
final String html = DOCTYPE_HTML
509+
+ "<html></head>\n"
510+
+ "<body>"
511+
+ "<script>\n"
512+
+ LOG_TITLE_FUNCTION
513+
+ "function CustomMap() {\n"
514+
+ " return Reflect.construct(Map, arguments, this.constructor);\n"
515+
+ "}\n"
516+
+ "CustomMap.prototype = Object.create(Map.prototype);\n"
517+
+ "CustomMap.prototype.constructor = CustomMap;\n"
518+
+ "var map = new CustomMap([['a', 1], ['b', 2]]);\n"
519+
+ "map.set('c', 3);\n"
520+
+ "log(Array.from(map.keys()));\n"
521+
+ "log(map instanceof CustomMap);\n"
522+
+ "log(map instanceof Map);\n"
523+
+ "log(Object.getPrototypeOf(map) === CustomMap.prototype);\n"
524+
+ "</script>\n"
525+
+ "</body></html>";
526+
527+
loadPageVerifyTitle2(html);
528+
}
529+
530+
/**
531+
* Test the same workaround for Array, which additionally propagates the subclass through
532+
* derived methods (map/filter/slice/...) via Symbol.species, and has exotic "length" and
533+
* isArray behavior that Set/Map don't.
534+
* @throws Exception if the test fails
535+
*/
536+
@Test
537+
@Alerts({"1,2,3", "true", "true", "true", "false", "true"})
538+
public void constructSubclassBuiltinArray() throws Exception {
539+
final String html = DOCTYPE_HTML
540+
+ "<html></head>\n"
541+
+ "<body>"
542+
+ "<script>\n"
543+
+ LOG_TITLE_FUNCTION
544+
+ "function CustomArray() {\n"
545+
+ " return Reflect.construct(Array, arguments, this.constructor);\n"
546+
+ "}\n"
547+
+ "CustomArray.prototype = Object.create(Array.prototype);\n"
548+
+ "CustomArray.prototype.constructor = CustomArray;\n"
549+
+ "var arr = new CustomArray(1, 2, 3);\n"
550+
+ "var mapped = arr.map(function(x) { return x * 2; });\n"
551+
+ "log(Array.from(arr));\n"
552+
+ "log(arr instanceof CustomArray);\n"
553+
+ "log(arr instanceof Array);\n"
554+
+ "log(Array.isArray(arr));\n"
555+
+ "log(mapped instanceof CustomArray);\n"
556+
+ "log(Object.getPrototypeOf(arr) === CustomArray.prototype);\n"
557+
+ "</script>\n"
558+
+ "</body></html>";
559+
560+
loadPageVerifyTitle2(html);
561+
}
562+
563+
/**
564+
* Test the workaround for WeakSet, which has no Symbol.iterator/Array.from support, so
565+
* membership must be verified via has() instead of reading contents out.
566+
* @throws Exception if the test fails
567+
*/
568+
@Test
569+
@Alerts({"true", "true", "true", "true"})
570+
public void constructSubclassBuiltinWeakSet() throws Exception {
571+
final String html = DOCTYPE_HTML
572+
+ "<html></head>\n"
573+
+ "<body>"
574+
+ "<script>\n"
575+
+ LOG_TITLE_FUNCTION
576+
+ "function CustomWeakSet() {\n"
577+
+ " return Reflect.construct(WeakSet, arguments, this.constructor);\n"
578+
+ "}\n"
579+
+ "CustomWeakSet.prototype = Object.create(WeakSet.prototype);\n"
580+
+ "CustomWeakSet.prototype.constructor = CustomWeakSet;\n"
581+
+ "var key = {};\n"
582+
+ "var ws = new CustomWeakSet([key]);\n"
583+
+ "ws.add({});\n"
584+
+ "log(ws.has(key));\n"
585+
+ "log(ws instanceof CustomWeakSet);\n"
586+
+ "log(ws instanceof WeakSet);\n"
587+
+ "log(Object.getPrototypeOf(ws) === CustomWeakSet.prototype);\n"
588+
+ "</script>\n"
589+
+ "</body></html>";
590+
591+
loadPageVerifyTitle2(html);
592+
}
593+
594+
/**
595+
* Test the workaround for a typed array (Uint8Array), which is species-driven like Array
596+
* (slice/subarray return instances via Symbol.species) and has an overloaded constructor
597+
* signature (length vs buffer vs iterable) that Set/Map don't have.
598+
* @throws Exception if the test fails
599+
*/
600+
@Test
601+
@Alerts({"1,2,3", "true", "false", "true", "true"})
602+
public void constructSubclassBuiltinTypedArray() throws Exception {
603+
final String html = DOCTYPE_HTML
604+
+ "<html></head>\n"
605+
+ "<body>"
606+
+ "<script>\n"
607+
+ LOG_TITLE_FUNCTION
608+
+ "function CustomUint8Array() {\n"
609+
+ " return Reflect.construct(Uint8Array, arguments, this.constructor);\n"
610+
+ "}\n"
611+
+ "CustomUint8Array.prototype = Object.create(Uint8Array.prototype);\n"
612+
+ "CustomUint8Array.prototype.constructor = CustomUint8Array;\n"
613+
+ "var ta = new CustomUint8Array([1, 2, 3]);\n"
614+
+ "var sliced = ta.slice(1);\n"
615+
+ "log(Array.from(ta));\n"
616+
+ "log(Object.getPrototypeOf(ta) === CustomUint8Array.prototype);\n"
617+
+ "log(Object.getPrototypeOf(ta) === Uint8Array.prototype);\n"
618+
+ "log(Object.getPrototypeOf(sliced) === Uint8Array.prototype);\n"
619+
+ "log(Object.getPrototypeOf(sliced) !== CustomUint8Array.prototype);\n"
620+
+ "</script>\n"
621+
+ "</body></html>";
622+
623+
loadPageVerifyTitle2(html);
624+
}
625+
626+
/**
627+
* Test the workaround applied to Proxy, which is expected to diverge from Set/Map/Array: a
628+
* Proxy without a getPrototypeOf trap forwards [[GetPrototypeOf]] to its target rather than to
629+
* whatever prototype Reflect.construct's newTarget would otherwise assign, since ProxyCreate
630+
* ignores newTarget entirely. So the proxy's actual prototype must be Object.prototype
631+
* (inherited from its target, a plain object), and must NOT be CustomProxy.prototype, even
632+
* though construction otherwise looks identical to the Set/Map/Array cases.
633+
* @throws Exception if the test fails
634+
*/
635+
@Test
636+
@Alerts({"true", "true", "true"})
637+
public void constructSubclassBuiltinProxy() throws Exception {
638+
final String html = DOCTYPE_HTML
639+
+ "<html></head>\n"
640+
+ "<body>"
641+
+ "<script>\n"
642+
+ LOG_TITLE_FUNCTION
643+
+ "function CustomProxy() {\n"
644+
+ " return Reflect.construct(Proxy, arguments, this.constructor);\n"
645+
+ "}\n"
646+
+ "CustomProxy.prototype = Object.create(Proxy.prototype || Object.prototype);\n"
647+
+ "CustomProxy.prototype.constructor = CustomProxy;\n"
648+
+ "var target = {};\n"
649+
+ "var p = new CustomProxy(target, {});\n"
650+
+ "log(Object.getPrototypeOf(p) === Object.prototype);\n"
651+
+ "log(Object.getPrototypeOf(p) === Object.getPrototypeOf(target));\n"
652+
+ "log(Object.getPrototypeOf(p) !== CustomProxy.prototype);\n"
653+
+ "</script>\n"
654+
+ "</body></html>";
655+
656+
loadPageVerifyTitle2(html);
657+
}
658+
659+
/**
660+
* Test the workaround for Error, included as a contrast case: unlike Set/Map/Array, naive
661+
* ES5-style inheritance (Error.call(this, message)) already gets most behavior "for free"
662+
* without Reflect.construct, since Error does not hold hidden internal slots the way the
663+
* collection/typed-array types do. This test documents that the Reflect.construct approach
664+
* still works, and still correctly wires up the prototype chain and instanceof checks.
665+
* @throws Exception if the test fails
666+
*/
667+
@Test
668+
@Alerts({"boom", "true", "true", "true"})
669+
public void constructSubclassBuiltinError() throws Exception {
670+
final String html = DOCTYPE_HTML
671+
+ "<html></head>\n"
672+
+ "<body>"
673+
+ "<script>\n"
674+
+ LOG_TITLE_FUNCTION
675+
+ "function CustomError() {\n"
676+
+ " var err = Reflect.construct(Error, arguments, this.constructor);\n"
677+
+ " return err;\n"
678+
+ "}\n"
679+
+ "CustomError.prototype = Object.create(Error.prototype);\n"
680+
+ "CustomError.prototype.constructor = CustomError;\n"
681+
+ "var err = new CustomError('boom');\n"
682+
+ "log(err.message);\n"
683+
+ "log(err instanceof CustomError);\n"
684+
+ "log(err instanceof Error);\n"
685+
+ "log(Object.getPrototypeOf(err) === CustomError.prototype);\n"
686+
+ "</script>\n"
687+
+ "</body></html>";
688+
689+
loadPageVerifyTitle2(html);
690+
}
494691
}

0 commit comments

Comments
 (0)