@pyscript/core 0.7.14 → 0.7.16

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.
Files changed (42) hide show
  1. package/dist/{codemirror-lkW_eC9r.js → codemirror-BIjK0FyF.js} +2 -2
  2. package/dist/{codemirror-lkW_eC9r.js.map → codemirror-BIjK0FyF.js.map} +1 -1
  3. package/dist/{codemirror_commands-DL2aL4qa.js → codemirror_commands-Ot159sys.js} +2 -2
  4. package/dist/{codemirror_commands-DL2aL4qa.js.map → codemirror_commands-Ot159sys.js.map} +1 -1
  5. package/dist/{codemirror_lang-python-DD5EtV36.js → codemirror_lang-python-BrxzY-1G.js} +2 -2
  6. package/dist/{codemirror_lang-python-DD5EtV36.js.map → codemirror_lang-python-BrxzY-1G.js.map} +1 -1
  7. package/dist/{codemirror_language-DRHeqAwG.js → codemirror_language-CGuBIifm.js} +2 -2
  8. package/dist/{codemirror_language-DRHeqAwG.js.map → codemirror_language-CGuBIifm.js.map} +1 -1
  9. package/dist/{codemirror_view-FN7LalDk.js → codemirror_view-C_m1bYT7.js} +2 -2
  10. package/dist/{codemirror_view-FN7LalDk.js.map → codemirror_view-C_m1bYT7.js.map} +1 -1
  11. package/dist/core-DDf1f5vl.js +4 -0
  12. package/dist/core-DDf1f5vl.js.map +1 -0
  13. package/dist/core.js +1 -1
  14. package/dist/{deprecations-manager-C3dm_nFe.js → deprecations-manager-B8ZteYqC.js} +2 -2
  15. package/dist/{deprecations-manager-C3dm_nFe.js.map → deprecations-manager-B8ZteYqC.js.map} +1 -1
  16. package/dist/{donkey-BEomLEVJ.js → donkey-CI8axTp4.js} +2 -2
  17. package/dist/{donkey-BEomLEVJ.js.map → donkey-CI8axTp4.js.map} +1 -1
  18. package/dist/{error-BxgMGRHm.js → error-B9rYJWCZ.js} +2 -2
  19. package/dist/{error-BxgMGRHm.js.map → error-B9rYJWCZ.js.map} +1 -1
  20. package/dist/{index-C-U2wRvV.js → index-DM-nsZEM.js} +2 -2
  21. package/dist/{index-C-U2wRvV.js.map → index-DM-nsZEM.js.map} +1 -1
  22. package/dist/{mpy-vg214mJz.js → mpy-BqUoeNzT.js} +2 -2
  23. package/dist/{mpy-vg214mJz.js.map → mpy-BqUoeNzT.js.map} +1 -1
  24. package/dist/{py-D41YGorm.js → py-_z3TfAz4.js} +2 -2
  25. package/dist/{py-D41YGorm.js.map → py-_z3TfAz4.js.map} +1 -1
  26. package/dist/{py-editor-CYTrIYru.js → py-editor-CZ3TM8k0.js} +2 -2
  27. package/dist/{py-editor-CYTrIYru.js.map → py-editor-CZ3TM8k0.js.map} +1 -1
  28. package/dist/{py-game-sxceV63x.js → py-game-DPu1fyiF.js} +2 -2
  29. package/dist/py-game-DPu1fyiF.js.map +1 -0
  30. package/dist/{py-terminal-DjW3NiNp.js → py-terminal-CkK0KvpF.js} +2 -2
  31. package/dist/{py-terminal-DjW3NiNp.js.map → py-terminal-CkK0KvpF.js.map} +1 -1
  32. package/dist/toml-V4Savzlc.js +3 -0
  33. package/dist/toml-V4Savzlc.js.map +1 -0
  34. package/dist/zip-CgZGjqjF.js.map +1 -1
  35. package/package.json +5 -5
  36. package/src/config.js +11 -8
  37. package/src/core.js +176 -187
  38. package/dist/core-CxWc2b7k.js +0 -4
  39. package/dist/core-CxWc2b7k.js.map +0 -1
  40. package/dist/py-game-sxceV63x.js.map +0 -1
  41. package/dist/toml-BK2RWy-G.js +0 -3
  42. package/dist/toml-BK2RWy-G.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pyscript/core",
3
- "version": "0.7.14",
3
+ "version": "0.7.16",
4
4
  "type": "module",
5
5
  "description": "PyScript",
6
6
  "module": "./index.js",
@@ -71,7 +71,7 @@
71
71
  "@webreflection/utils": "^0.1.1",
72
72
  "add-promise-listener": "^0.1.3",
73
73
  "basic-devtools": "^0.1.6",
74
- "polyscript": "^0.20.5",
74
+ "polyscript": "^0.20.8",
75
75
  "sticky-module": "^0.1.1",
76
76
  "to-json-callback": "^0.1.1",
77
77
  "type-checked-collections": "^0.1.7"
@@ -82,7 +82,7 @@
82
82
  "@codemirror/language": "^6.12.1",
83
83
  "@codemirror/state": "^6.5.4",
84
84
  "@codemirror/view": "^6.39.11",
85
- "@playwright/test": "^1.57.0",
85
+ "@playwright/test": "^1.58.0",
86
86
  "@rollup/plugin-commonjs": "^29.0.0",
87
87
  "@rollup/plugin-node-resolve": "^16.0.3",
88
88
  "@rollup/plugin-terser": "^0.4.4",
@@ -90,13 +90,13 @@
90
90
  "@xterm/addon-fit": "0.11.0",
91
91
  "@xterm/addon-web-links": "0.12.0",
92
92
  "@xterm/xterm": "5.5.0",
93
- "bun": "^1.3.6",
93
+ "bun": "^1.3.7",
94
94
  "chokidar": "^5.0.0",
95
95
  "codedent": "^0.1.2",
96
96
  "codemirror": "^6.0.2",
97
97
  "eslint": "^9.39.2",
98
98
  "flatted": "^3.3.3",
99
- "rollup": "^4.55.3",
99
+ "rollup": "^4.57.0",
100
100
  "rollup-plugin-postcss": "^4.0.2",
101
101
  "rollup-plugin-string": "^3.0.0",
102
102
  "static-handler": "^0.5.3",
package/src/config.js CHANGED
@@ -9,6 +9,7 @@ import TYPES from "./types.js";
9
9
  import allPlugins from "./plugins.js";
10
10
  import { robustFetch as fetch, getText } from "./fetch.js";
11
11
  import { ErrorCode } from "./exceptions.js";
12
+ import { toml as tomlParser } from "polyscript/exports";
12
13
 
13
14
  const { BAD_CONFIG, CONFLICTING_CODE } = ErrorCode;
14
15
 
@@ -43,6 +44,11 @@ export const configDetails = async (config, type) => {
43
44
  return { json, toml: toml || (!json && !!text), text, url };
44
45
  };
45
46
 
47
+ const configParser = pyElement => {
48
+ const parser = pyElement.getAttribute("config-parser");
49
+ return parser ? new URL(parser, location.href).href : undefined;
50
+ };
51
+
46
52
  const conflictError = (reason) => new Error(`(${CONFLICTING_CODE}): ${reason}`);
47
53
 
48
54
  const relative_url = (url, base = location.href) => new URL(url, base).href;
@@ -93,11 +99,11 @@ for (const [TYPE] of TYPES) {
93
99
  [pyElement] = pyConfigs;
94
100
  config = pyElement.getAttribute("src") || pyElement.textContent;
95
101
  type = pyElement.getAttribute("type");
96
- parser = pyElement.getAttribute("config-parser");
102
+ parser = configParser(pyElement);
97
103
  } else if (attrConfigs.length) {
98
104
  [pyElement, ...attrConfigs] = attrConfigs;
99
105
  config = pyElement.getAttribute("config");
100
- parser = pyElement.getAttribute("config-parser");
106
+ parser = configParser(pyElement);
101
107
  // throw an error if dirrent scripts use different configs
102
108
  if (
103
109
  attrConfigs.some((el) => el.getAttribute("config") !== config)
@@ -125,11 +131,8 @@ for (const [TYPE] of TYPES) {
125
131
  try {
126
132
  const module = parser
127
133
  ? await import(parser)
128
- : await import(
129
- /* webpackIgnore: true */ "./3rd-party/toml.js"
130
- );
131
- const parse = module.parse || module.default;
132
- parsed = parse(text);
134
+ : await tomlParser(text).then(json => ({ parse: () => json }));
135
+ parsed = (module.parse || module.default)(text);
133
136
  } catch (e) {
134
137
  error = syntaxError("TOML", url, e);
135
138
  }
@@ -163,7 +166,7 @@ for (const [TYPE] of TYPES) {
163
166
  if (Number.isSafeInteger(parsed?.experimental_ffi_timeout))
164
167
  globalThis.reflected_ffi_timeout = parsed?.experimental_ffi_timeout;
165
168
 
166
- configs.set(TYPE, { config: parsed, configURL, plugins, error });
169
+ configs.set(TYPE, { config: parsed, configURL, parser, plugins, error });
167
170
  }
168
171
 
169
172
  export { configs, relative_url };
package/src/core.js CHANGED
@@ -117,7 +117,7 @@ for (const [TYPE, interpreter] of TYPES) {
117
117
  else dispatch(element, TYPE, "done");
118
118
  };
119
119
 
120
- let { config, configURL, plugins, error } = configs.get(TYPE);
120
+ let { config, configURL, parser, plugins, error } = configs.get(TYPE);
121
121
 
122
122
  // create a unique identifier when/if needed
123
123
  let id = 0;
@@ -180,201 +180,190 @@ for (const [TYPE, interpreter] of TYPES) {
180
180
  });
181
181
  };
182
182
 
183
- // define the module as both `<script type="py">` and `<py-script>`
184
- // but only if the config didn't throw an error
185
- if (!error) {
186
- // ensure plugins are bootstrapped already before custom type definition
187
- // NOTE: we cannot top-level await in here as plugins import other utilities
188
- // from core.js itself so that custom definition should not be blocking.
189
- plugins().then(() => {
190
- // possible early errors sent by polyscript
191
- const errors = new Map();
192
-
193
- // specific main and worker hooks
194
- const hooks = {
195
- main: {
196
- ...codeFor(main, TYPE),
197
- async onReady(wrap, element) {
198
- registerModule(wrap);
199
-
200
- // allows plugins to do whatever they want with the element
201
- // before regular stuff happens in here
202
- for (const callback of main("onReady"))
203
- await callback(wrap, element);
204
-
205
- // now that all possible plugins are configured,
206
- // bail out if polyscript encountered an error
207
- if (errors.has(element)) {
208
- let { message } = errors.get(element);
209
- errors.delete(element);
210
- const clone = message === INVALID_CONTENT;
211
- message = `(${ErrorCode.CONFLICTING_CODE}) ${message} for `;
212
- message += element.cloneNode(clone).outerHTML;
213
- wrap.io.stderr(message);
214
- return;
215
- }
183
+ // ensure plugins are bootstrapped already before custom type definition
184
+ // NOTE: we cannot top-level await in here as plugins import other utilities
185
+ // from core.js itself so that custom definition should not be blocking.
186
+ plugins().then(() => {
187
+ // let plugins logic decide how to show the error but stop here if any
188
+ if (error) return;
189
+
190
+ // possible early errors sent by polyscript
191
+ const errors = new Map();
192
+
193
+ // specific main and worker hooks
194
+ const hooks = {
195
+ main: {
196
+ ...codeFor(main, TYPE),
197
+ async onReady(wrap, element) {
198
+ registerModule(wrap);
199
+
200
+ // allows plugins to do whatever they want with the element
201
+ // before regular stuff happens in here
202
+ for (const callback of main("onReady"))
203
+ await callback(wrap, element);
204
+
205
+ // now that all possible plugins are configured,
206
+ // bail out if polyscript encountered an error
207
+ if (errors.has(element)) {
208
+ let { message } = errors.get(element);
209
+ errors.delete(element);
210
+ const clone = message === INVALID_CONTENT;
211
+ message = `(${ErrorCode.CONFLICTING_CODE}) ${message} for `;
212
+ message += element.cloneNode(clone).outerHTML;
213
+ wrap.io.stderr(message);
214
+ return;
215
+ }
216
216
 
217
- if (isScript(element)) {
218
- const isAsync = !isSync(element);
219
- const target = element.getAttribute("target");
220
- const show = target
221
- ? queryTarget(element, target)
222
- : document.createElement("script-py");
223
-
224
- if (!target) {
225
- const { head, body } = document;
226
- if (head.contains(element)) body.append(show);
227
- else element.after(show);
228
- }
229
- if (!show.id) show.id = getID();
230
-
231
- // allows the code to retrieve the target element via
232
- // document.currentScript.target if needed
233
- defineProperty(element, "target", { value: show });
234
-
235
- // notify before the code runs
236
- dispatch(element, TYPE, "ready");
237
- dispatchDone(
238
- element,
239
- isAsync,
240
- wrap[`run${isAsync ? "Async" : ""}`](
241
- await fetchSource(element, wrap.io, true),
242
- ),
243
- );
244
- } else {
245
- // resolve PyScriptElement to allow connectedCallback
246
- element._wrap.resolve(wrap);
217
+ if (isScript(element)) {
218
+ const isAsync = !isSync(element);
219
+ const target = element.getAttribute("target");
220
+ const show = target
221
+ ? queryTarget(element, target)
222
+ : document.createElement("script-py");
223
+
224
+ if (!target) {
225
+ const { head, body } = document;
226
+ if (head.contains(element)) body.append(show);
227
+ else element.after(show);
247
228
  }
248
- console.debug("[pyscript/main] PyScript Ready");
249
- },
250
- onWorker(_, xworker) {
251
- assign(xworker.sync, sync);
252
- for (const callback of main("onWorker"))
253
- callback(_, xworker);
254
- },
255
- onBeforeRun(wrap, element) {
256
- currentElement = element;
257
- bootstrapNodeAndPlugins(
258
- main,
259
- wrap,
260
- element,
261
- "onBeforeRun",
262
- );
263
- },
264
- onBeforeRunAsync(wrap, element) {
265
- currentElement = element;
266
- return bootstrapNodeAndPlugins(
267
- main,
268
- wrap,
269
- element,
270
- "onBeforeRunAsync",
271
- );
272
- },
273
- onAfterRun(wrap, element) {
274
- bootstrapNodeAndPlugins(
275
- main,
276
- wrap,
277
- element,
278
- "onAfterRun",
279
- );
280
- },
281
- onAfterRunAsync(wrap, element) {
282
- return bootstrapNodeAndPlugins(
283
- main,
284
- wrap,
229
+ if (!show.id) show.id = getID();
230
+
231
+ // allows the code to retrieve the target element via
232
+ // document.currentScript.target if needed
233
+ defineProperty(element, "target", { value: show });
234
+
235
+ // notify before the code runs
236
+ dispatch(element, TYPE, "ready");
237
+ dispatchDone(
285
238
  element,
286
- "onAfterRunAsync",
239
+ isAsync,
240
+ wrap[`run${isAsync ? "Async" : ""}`](
241
+ await fetchSource(element, wrap.io, true),
242
+ ),
287
243
  );
288
- },
244
+ } else {
245
+ // resolve PyScriptElement to allow connectedCallback
246
+ element._wrap.resolve(wrap);
247
+ }
248
+ console.debug("[pyscript/main] PyScript Ready");
289
249
  },
290
- worker: {
291
- ...codeFor(worker, TYPE),
292
- // these are lazy getters that returns a composition
293
- // of the current hooks or undefined, if no hook is present
294
- get onReady() {
295
- return createFunction(this, "onReady", true);
296
- },
297
- get onBeforeRun() {
298
- return createFunction(this, "onBeforeRun", false);
299
- },
300
- get onBeforeRunAsync() {
301
- return createFunction(this, "onBeforeRunAsync", true);
302
- },
303
- get onAfterRun() {
304
- return createFunction(this, "onAfterRun", false);
305
- },
306
- get onAfterRunAsync() {
307
- return createFunction(this, "onAfterRunAsync", true);
308
- },
250
+ onWorker(_, xworker) {
251
+ assign(xworker.sync, sync);
252
+ for (const callback of main("onWorker"))
253
+ callback(_, xworker);
309
254
  },
310
- };
311
-
312
- hooked.set(TYPE, hooks);
313
-
314
- // allow offline interpreter detection via [offline] attribute
315
- let version = offline_interpreter(config);
316
- if (!version) {
317
- const css = "script[type='module'][offline]";
318
- const s = document.querySelector(css)?.src;
319
- if (s && import.meta.url.startsWith(s.replace(/\.js$/, ""))) {
320
- version = `./pyscript/${interpreter}/${interpreter}.mjs`;
321
- version = offline_interpreter({ interpreter: version });
322
- }
323
- }
324
-
325
- define(TYPE, {
326
- config,
327
- configURL,
328
- interpreter,
329
- hooks,
330
- version,
331
- env: `${TYPE}-script`,
332
- onerror(error, element) {
333
- errors.set(element, error);
255
+ onBeforeRun(wrap, element) {
256
+ currentElement = element;
257
+ bootstrapNodeAndPlugins(main, wrap, element, "onBeforeRun");
334
258
  },
335
- });
336
-
337
- customElements.define(
338
- `${TYPE}-script`,
339
- class extends HTMLElement {
340
- constructor() {
341
- assign(super(), {
342
- _wrap: withResolvers(),
343
- srcCode: "",
344
- executed: false,
345
- });
346
- }
347
- get id() {
348
- return super.id || (super.id = getID());
349
- }
350
- set id(value) {
351
- super.id = value;
352
- }
353
- async connectedCallback() {
354
- if (!this.executed) {
355
- this.executed = true;
356
- const isAsync = !isSync(this);
357
- const { io, run, runAsync } = await this._wrap
358
- .promise;
359
- this.srcCode = await fetchSource(
360
- this,
361
- io,
362
- !this.childElementCount,
363
- );
364
- this.replaceChildren();
365
- this.style.display = "block";
366
- dispatch(this, TYPE, "ready");
367
- dispatchDone(
368
- this,
369
- isAsync,
370
- (isAsync ? runAsync : run)(this.srcCode),
371
- );
372
- }
373
- }
259
+ onBeforeRunAsync(wrap, element) {
260
+ currentElement = element;
261
+ return bootstrapNodeAndPlugins(
262
+ main,
263
+ wrap,
264
+ element,
265
+ "onBeforeRunAsync",
266
+ );
374
267
  },
375
- );
268
+ onAfterRun(wrap, element) {
269
+ bootstrapNodeAndPlugins(main, wrap, element, "onAfterRun");
270
+ },
271
+ onAfterRunAsync(wrap, element) {
272
+ return bootstrapNodeAndPlugins(
273
+ main,
274
+ wrap,
275
+ element,
276
+ "onAfterRunAsync",
277
+ );
278
+ },
279
+ },
280
+ worker: {
281
+ ...codeFor(worker, TYPE),
282
+ // these are lazy getters that returns a composition
283
+ // of the current hooks or undefined, if no hook is present
284
+ get onReady() {
285
+ return createFunction(this, "onReady", true);
286
+ },
287
+ get onBeforeRun() {
288
+ return createFunction(this, "onBeforeRun", false);
289
+ },
290
+ get onBeforeRunAsync() {
291
+ return createFunction(this, "onBeforeRunAsync", true);
292
+ },
293
+ get onAfterRun() {
294
+ return createFunction(this, "onAfterRun", false);
295
+ },
296
+ get onAfterRunAsync() {
297
+ return createFunction(this, "onAfterRunAsync", true);
298
+ },
299
+ },
300
+ };
301
+
302
+ hooked.set(TYPE, hooks);
303
+
304
+ // allow offline interpreter detection via [offline] attribute
305
+ let version = offline_interpreter(config);
306
+ if (!version) {
307
+ const css = "script[type='module'][offline]";
308
+ const s = document.querySelector(css)?.src;
309
+ if (s && import.meta.url.startsWith(s.replace(/\.js$/, ""))) {
310
+ version = `./pyscript/${interpreter}/${interpreter}.mjs`;
311
+ version = offline_interpreter({ interpreter: version });
312
+ }
313
+ }
314
+
315
+ define(TYPE, {
316
+ config,
317
+ configURL,
318
+ interpreter,
319
+ hooks,
320
+ version,
321
+ env: `${TYPE}-script`,
322
+ parser: parser && new URL(parser, location.href).href,
323
+ onerror(error, element) {
324
+ errors.set(element, error);
325
+ },
376
326
  });
377
- }
327
+
328
+ customElements.define(
329
+ `${TYPE}-script`,
330
+ class extends HTMLElement {
331
+ constructor() {
332
+ assign(super(), {
333
+ _wrap: withResolvers(),
334
+ srcCode: "",
335
+ executed: false,
336
+ });
337
+ }
338
+ get id() {
339
+ return super.id || (super.id = getID());
340
+ }
341
+ set id(value) {
342
+ super.id = value;
343
+ }
344
+ async connectedCallback() {
345
+ if (!this.executed) {
346
+ this.executed = true;
347
+ const isAsync = !isSync(this);
348
+ const { io, run, runAsync } = await this._wrap.promise;
349
+ this.srcCode = await fetchSource(
350
+ this,
351
+ io,
352
+ !this.childElementCount,
353
+ );
354
+ this.replaceChildren();
355
+ this.style.display = "block";
356
+ dispatch(this, TYPE, "ready");
357
+ dispatchDone(
358
+ this,
359
+ isAsync,
360
+ (isAsync ? runAsync : run)(this.srcCode),
361
+ );
362
+ }
363
+ }
364
+ },
365
+ );
366
+ });
378
367
 
379
368
  // export the used config without allowing leaks through it
380
369
  exportedConfig[TYPE] = structuredClone(config);