Add JS test for constructing FXJSOBJTYPE_DYNAMIC objects.

These won't be full-fledged objects since they lack C++ bindings
(as tested in icons.in), but they shouldn't allow their constructor
to be invoked as a plain function.

Change-Id: I9be1eddfc6dc4eb2d836670c0eb3fd095c7bde8f
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/66171
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/testing/resources/javascript/constructor.in b/testing/resources/javascript/constructor.in
index 61ce579..90c41c0 100644
--- a/testing/resources/javascript/constructor.in
+++ b/testing/resources/javascript/constructor.in
@@ -33,8 +33,12 @@
 >>
 stream
 {{include constructor.js}}
+
+// Global objects
 testIllegalConstructor("this");
 testIllegalConstructor("globalThis");
+
+// Static objects
 testIllegalConstructor("app");
 testIllegalConstructor("event");
 testIllegalConstructor("font");
@@ -50,6 +54,11 @@
 testIllegalConstructor("zoomtype");
 testIllegalConstructor("scaleHow");
 testIllegalConstructor("scaleWhen");
+
+// Dynamic objects
+timer1 = app.setTimeOut("var marked = true", 1000);
+testLegalConstructor("timer1");
+
 endstream
 endobj
 {{xref}}
diff --git a/testing/resources/javascript/constructor.js b/testing/resources/javascript/constructor.js
index bc6d478..00c0eab 100644
--- a/testing/resources/javascript/constructor.js
+++ b/testing/resources/javascript/constructor.js
@@ -2,9 +2,32 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+function testLegalConstructor(name, allowed) {
+  const constructorString = name + ".constructor";
+  var constructor;
+  try {
+    constructor = eval(constructorString);
+  } catch (e) {
+    app.alert("FAIL: No such " + constructorString);
+    return;
+  }
+  try {
+    constructor();
+    app.alert("FAIL: " + constructorString + "(): returned");
+  } catch (e) {
+    app.alert("PASS: " + constructorString + "(): " + e);
+  }
+  try {
+    var thing = new constructor;
+    app.alert("PASS: new " + constructorString + ": " + thing);
+  } catch (e) {
+    app.alert("FAIL: new " + constructorString + ": " + e);
+  }
+}
+
 function testIllegalConstructor(name, allowed) {
   const constructorString = name + ".constructor";
-  let constructor;
+  var constructor;
   try {
     constructor = eval(constructorString);
   } catch (e) {
diff --git a/testing/resources/javascript/constructor_expected.txt b/testing/resources/javascript/constructor_expected.txt
index bb13a3a..8c58aad 100644
--- a/testing/resources/javascript/constructor_expected.txt
+++ b/testing/resources/javascript/constructor_expected.txt
@@ -32,3 +32,5 @@
 Alert: PASS: new scaleHow.constructor: not a dynamic object
 Alert: PASS: scaleWhen.constructor(): illegal constructor
 Alert: PASS: new scaleWhen.constructor: not a dynamic object
+Alert: PASS: timer1.constructor(): illegal constructor
+Alert: PASS: new timer1.constructor: [object Object]