sandbox-globals.html 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. <p>Run it both in Chrome and FF</p>
  2. <textarea id="results" style="width:30em; height: 90%" spellcheck="false"></textarea>
  3. <script>
  4. const el = document.getElementById('results');
  5. el.value = [
  6. function boundMethods(isHeader) {
  7. const keys = [];
  8. /* global globalThis */
  9. for (const k in globalThis) {
  10. if (k >= 'a' && k <= 'z') {
  11. const { value } = Object.getOwnPropertyDescriptor(globalThis, k)
  12. || Object.getOwnPropertyDescriptor(EventTarget.prototype, k)
  13. || Object.getOwnPropertyDescriptor(Object.prototype, k)
  14. || {};
  15. if (typeof value === 'function') {
  16. if (k === 'createImageBitmap' || k === 'fetch') {
  17. keys.push(k);
  18. } else {
  19. try {
  20. globalThis[k].call({});
  21. } catch (e) {
  22. if (/Illegal invocation|implement interface/.test(e)) {
  23. keys.push(k);
  24. }
  25. }
  26. }
  27. }
  28. }
  29. }
  30. return {
  31. header: "const MAYBE = vmOwnFunc; // something that can't be imitated by the page\n",
  32. keys: keys,
  33. value: 'MAYBE',
  34. };
  35. },
  36. function unforgeables() {
  37. return Object.entries(Object.getOwnPropertyDescriptors(window))
  38. .filter(([, v]) => !v.configurable)
  39. .map(([k]) => k);
  40. },
  41. function readonlyKeys() {
  42. return Object.entries(Object.getOwnPropertyDescriptors(window))
  43. .filter(([k, v]) => k >= 'a' && k <= 'z'
  44. && k !== 'webkitStorageInfo' // deprecated
  45. && v.get && !v.set && v.configurable)
  46. .map(([k]) => k);
  47. },
  48. ].map(fn => {
  49. let res = fn();
  50. if (Array.isArray(res)) res = { keys: res };
  51. return `${res.header || ''}const ${fn.name} = {
  52. __proto__: null,
  53. ${
  54. res.keys.sort()
  55. .map(k => ` ${k}: ${res.value || 1},`)
  56. .join('\n')
  57. }
  58. }
  59. `;
  60. }).join('\n');
  61. el.focus();
  62. el.select();
  63. </script>