Bug 1615861 - Support calling Proxy and Reflect methods when doing eager evaluations. r=nchevobbe
authorOriol Brufau <oriol-bugzilla@hotmail.com>
Mon, 17 Feb 2020 15:12:01 +0000
changeset 514326 50ce9805294b08da6fe5349a7884553ad4530c25
parent 514325 033702e7e3837828824e693c92d203ae838fe797
child 514327 08149dc0e96856bd85bc075112b66fe1572e2b62
push id107506
push userccoroiu@mozilla.com
push dateMon, 17 Feb 2020 15:33:26 +0000
treeherderautoland@50ce9805294b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnchevobbe
bugs1615861
milestone75.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1615861 - Support calling Proxy and Reflect methods when doing eager evaluations. r=nchevobbe Differential Revision: https://phabricator.services.mozilla.com/D63008
devtools/client/webconsole/test/browser/browser_jsterm_eager_evaluation.js
devtools/server/actors/webconsole/eval-with-debugger.js
--- a/devtools/client/webconsole/test/browser/browser_jsterm_eager_evaluation.js
+++ b/devtools/client/webconsole/test/browser/browser_jsterm_eager_evaluation.js
@@ -104,16 +104,129 @@ add_task(async function() {
   info("Switch to editor mode");
   await toggleLayout(hud);
   await waitForEagerEvaluationResult(hud, `"> result: 7"`);
   ok(true, "eager evaluation is still displayed in editor mode");
 
   setInputValue(hud, "4 + 7");
   await waitForEagerEvaluationResult(hud, "11");
 
+  setInputValue(hud, "typeof new Proxy({}, {})");
+  await waitForEagerEvaluationResult(hud, `"object"`);
+
+  setInputValue(hud, "typeof Proxy.revocable({}, {}).revoke");
+  await waitForEagerEvaluationResult(hud, `"function"`);
+
+  setInputValue(hud, "Reflect.apply(() => 1, null, [])");
+  await waitForEagerEvaluationResult(hud, "1");
+  setInputValue(
+    hud,
+    `Reflect.apply(() => {
+      globalThis.sideEffect = true;
+      return 2;
+    }, null, [])`
+  );
+  await waitForNoEagerEvaluationResult(hud);
+
+  setInputValue(hud, "Reflect.construct(Array, []).length");
+  await waitForEagerEvaluationResult(hud, "0");
+  setInputValue(
+    hud,
+    `Reflect.construct(function() {
+      globalThis.sideEffect = true;
+    }, [])`
+  );
+  await waitForNoEagerEvaluationResult(hud);
+
+  setInputValue(hud, "Reflect.defineProperty({}, 'a', {value: 1})");
+  await waitForNoEagerEvaluationResult(hud);
+
+  setInputValue(hud, "Reflect.deleteProperty({a: 1}, 'a')");
+  await waitForNoEagerEvaluationResult(hud);
+
+  setInputValue(hud, "Reflect.get({a: 1}, 'a')");
+  await waitForEagerEvaluationResult(hud, "1");
+  setInputValue(hud, "Reflect.get({get a(){return 2}, 'a')");
+  await waitForNoEagerEvaluationResult(hud);
+
+  setInputValue(hud, "Reflect.getOwnPropertyDescriptor({a: 1}, 'a').value");
+  await waitForEagerEvaluationResult(hud, "1");
+  setInputValue(
+    hud,
+    `Reflect.getOwnPropertyDescriptor(
+      new Proxy({ a: 2 }, { getOwnPropertyDescriptor() {
+        globalThis.sideEffect = true;
+        return { value: 2 };
+      }}),
+      "a"
+    )`
+  );
+  await waitForNoEagerEvaluationResult(hud);
+
+  setInputValue(hud, "Reflect.getPrototypeOf({}) === Object.prototype");
+  await waitForEagerEvaluationResult(hud, "true");
+  setInputValue(
+    hud,
+    `Reflect.getPrototypeOf(
+      new Proxy({}, { getPrototypeOf() {
+        globalThis.sideEffect = true;
+        return null;
+      }})
+    )`
+  );
+  await waitForNoEagerEvaluationResult(hud);
+
+  setInputValue(hud, "Reflect.has({a: 1}, 'a')");
+  await waitForEagerEvaluationResult(hud, "true");
+  setInputValue(
+    hud,
+    `Reflect.has(
+      new Proxy({ a: 2 }, { has() {
+        globalThis.sideEffect = true;
+        return true;
+      }}), "a"
+    )`
+  );
+  await waitForNoEagerEvaluationResult(hud);
+
+  setInputValue(hud, "Reflect.isExtensible({})");
+  await waitForEagerEvaluationResult(hud, "true");
+  setInputValue(
+    hud,
+    `Reflect.isExtensible(
+      new Proxy({}, { isExtensible() {
+        globalThis.sideEffect = true;
+        return true;
+      }})
+    )`
+  );
+  await waitForNoEagerEvaluationResult(hud);
+
+  setInputValue(hud, "Reflect.ownKeys({a: 1})[0]");
+  await waitForEagerEvaluationResult(hud, `"a"`);
+  setInputValue(
+    hud,
+    `Reflect.ownKeys(
+      new Proxy({}, { ownKeys() {
+        globalThis.sideEffect = true;
+        return ['a'];
+      }})
+    )`
+  );
+  await waitForNoEagerEvaluationResult(hud);
+
+  setInputValue(hud, "Reflect.preventExtensions({})");
+  await waitForNoEagerEvaluationResult(hud);
+
+  setInputValue(hud, "Reflect.set({}, 'a', 1)");
+  await waitForNoEagerEvaluationResult(hud);
+
+  setInputValue(hud, "Reflect.setPrototypeOf({}, null)");
+  await waitForNoEagerEvaluationResult(hud);
+
   // go back to inline layout.
   await toggleLayout(hud);
 });
 
 // Test that the currently selected autocomplete result is eagerly evaluated.
 add_task(async function() {
   await pushPref(EAGER_EVALUATION_PREF, true);
   const hud = await openNewTabAndConsole(TEST_URI);
--- a/devtools/server/actors/webconsole/eval-with-debugger.js
+++ b/devtools/server/actors/webconsole/eval-with-debugger.js
@@ -446,16 +446,26 @@ function ensureSideEffectFreeNatives() {
     Object.getPrototypeOf,
     Object.is,
     Object.isExtensible,
     Object.isFrozen,
     Object.isSealed,
     Object.values,
     Object.prototype.hasOwnProperty,
     Object.prototype.isPrototypeOf,
+    Proxy,
+    Proxy.revocable,
+    Reflect.apply,
+    Reflect.construct,
+    Reflect.get,
+    Reflect.getOwnPropertyDescriptor,
+    Reflect.getPrototypeOf,
+    Reflect.has,
+    Reflect.isExtensible,
+    Reflect.ownKeys,
     RegExp,
     RegExp.prototype.exec,
     RegExp.prototype.test,
     Set,
     Set.prototype.entries,
     Set.prototype.forEach,
     Set.prototype.has,
     Set.prototype.values,