@trailstash/ultra 5.0.1 → 5.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -357,7 +357,15 @@ export class UltraMap extends HTMLElement {
357
357
  });
358
358
  if (this.transform) {
359
359
  if (sandbox) {
360
- source.data = await sandbox(this.transform, source.data);
360
+ source.data = await Promise.race([
361
+ sandbox(this.transform, source.data),
362
+ new Promise((resolve, reject) => {
363
+ controller.signal.onabort = () => {
364
+ this.#cachedTransform = null;
365
+ reject(new DOMException("", "AbortError"));
366
+ };
367
+ }),
368
+ ]);
361
369
  } else {
362
370
  throw new Error("sandbox could not be initialized");
363
371
  }
@@ -62,6 +62,9 @@ export const getQueryFromQueryParams = () => {
62
62
  // query
63
63
  if (params.has("q")) {
64
64
  query = decompressFromEncodedURIComponent(params.get("q"));
65
+ if (!query) {
66
+ alert("Invalid compressed query specified in URL");
67
+ }
65
68
  } else if (params.has("query")) {
66
69
  query = params.get("query");
67
70
  if (query.startsWith("gist:")) {
@@ -111,6 +114,16 @@ export const getOptionsFromQueryParams = () => {
111
114
  };
112
115
 
113
116
  export const getAutoRunFromQueryParams = () => {
117
+ // Don't autorun if provided query can't be decompressed
118
+ // TODO: other query load errors?
119
+ const params = new URLSearchParams(window.location.hash.slice(1));
120
+ if (params.has("q")) {
121
+ const query = decompressFromEncodedURIComponent(params.get("q"));
122
+ if (!query) {
123
+ return false;
124
+ }
125
+ }
126
+
114
127
  return new URLSearchParams(window.location.hash.slice(1)).has("run");
115
128
  };
116
129
 
package/lib/sandbox.js CHANGED
@@ -1,46 +1,104 @@
1
- const makeSandbox = () => {
2
- const iframe = window.document.createElement("iframe");
3
- const sandboxId = crypto.randomUUID();
4
- iframe.style.display = "none";
5
- iframe.src =
6
- "data:text/html;base64," +
7
- btoa(`<!DOCTYPE html>
8
- <script type="module">
9
- const p = "${window.location.origin}"
10
-
11
- window.addEventListener(
1
+ const sandboxInit = async (sandboxId, p) => {
2
+ const workerInit = (workerId) => {
3
+ self.addEventListener(
12
4
  "message",
13
5
  async (event) => {
14
- console.debug(event);
15
-
16
- if (event.origin !== p) return;
6
+ console.debug("worker recived msg from sandbox", event);
17
7
 
18
8
  let id;
19
9
  try {
20
10
  const msg = JSON.parse(event.data);
21
11
  id = msg.id;
22
- console.debug(msg)
12
+ console.debug("parsed message", msg);
23
13
 
24
14
  const { default: transform } = await import(msg.transform);
25
15
 
26
16
  const o = await Promise.resolve(transform(msg.data));
27
- event.source.postMessage(JSON.stringify({id: msg.id, data: o}), p);
17
+ self.postMessage(JSON.stringify({ id: msg.id, data: o }));
28
18
  } catch (e) {
29
- event.source.postMessage(JSON.stringify({id: id, error: e.toString()}), p);
19
+ self.postMessage(JSON.stringify({ id: id, error: e.toString() }));
30
20
  }
31
21
  },
32
22
  false,
33
23
  );
34
24
 
35
- window.parent.postMessage(JSON.stringify({id: "${sandboxId}"}), p);
36
- </script>
37
- `);
25
+ self.postMessage(JSON.stringify({ id: workerId }));
26
+ };
27
+
28
+ const workerBlob = new Blob([`(${workerInit.toString()})("${sandboxId}");`], {
29
+ type: "module",
30
+ });
31
+ const worker = new Worker(URL.createObjectURL(workerBlob));
32
+
33
+ const waitForWorkerReady = () =>
34
+ new Promise((resolve, reject) => {
35
+ const listener = (event) => {
36
+ worker.removeEventListener("message", listener, false);
37
+ console.debug("sandbox recived msg from worker", event);
38
+ try {
39
+ const msg = JSON.parse(event.data);
40
+ if (msg.id === sandboxId) {
41
+ resolve();
42
+ return;
43
+ }
44
+ console.warn("unexpected msg!");
45
+ } catch (e) {
46
+ reject(e);
47
+ return;
48
+ }
49
+ };
50
+ worker.addEventListener("message", listener, false);
51
+ });
52
+
53
+ // wait for ready msg from worker
54
+ await waitForWorkerReady();
55
+ console.log("worker ready");
56
+
57
+ // Relay messages from parent to worker
58
+ window.addEventListener(
59
+ "message",
60
+ (event) => {
61
+ console.debug("sandbox recieved msg from parent", event);
62
+ worker.postMessage(event.data);
63
+ },
64
+ false,
65
+ );
66
+ // Relay messages from worker to parent
67
+ worker.addEventListener(
68
+ "message",
69
+ (event) => {
70
+ console.debug("sandbox recieved msg from worker", event);
71
+ window.parent.postMessage(event.data, p);
72
+ },
73
+ false,
74
+ );
75
+
76
+ window.parent.postMessage(JSON.stringify({ id: sandboxId }), p);
77
+ };
78
+ const makeSandbox = () => {
79
+ const iframe = window.document.createElement("iframe");
80
+ const sandboxId = crypto.randomUUID();
81
+ iframe.style.display = "none";
82
+ const sandboxBlob = new Blob(
83
+ [
84
+ `
85
+ <!DOCTYPE html>
86
+ <script type="module">
87
+ (${sandboxInit.toString()})("${sandboxId}", "${window.location.origin}");
88
+ </script>
89
+ `,
90
+ ],
91
+ {
92
+ type: "text/html",
93
+ },
94
+ );
95
+ iframe.src = URL.createObjectURL(sandboxBlob);
38
96
 
39
97
  const run = (transform, data) => {
40
98
  const messageID = crypto.randomUUID();
41
99
  return new Promise((resolve, reject) => {
42
100
  const listener = (event) => {
43
- console.debug(event);
101
+ console.debug("parent recieved msg from sandbox", event);
44
102
  try {
45
103
  const msg = JSON.parse(event.data);
46
104
  if (msg.id === messageID) {
@@ -73,10 +131,11 @@ const makeSandbox = () => {
73
131
  return new Promise((resolve) => {
74
132
  const listener = (event) => {
75
133
  window.removeEventListener("message", listener, false);
76
- console.debug(event);
134
+ console.debug("parent recieved msg from sandbox", event);
77
135
  try {
78
136
  const msg = JSON.parse(event.data);
79
137
  if (msg.id === sandboxId) {
138
+ console.log("sandbox ready");
80
139
  resolve(run);
81
140
  return;
82
141
  }
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "5.0.1",
6
+ "version": "5.0.3",
7
7
  "description": "A web based tool for making MapLibre GL maps with data from sources such as Overpass, GeoJSON, GPX, KML, TCX, etc",
8
8
  "main": "index.js",
9
9
  "scripts": {