[next] Errors on ambiguous/conflicting code intents (#1724)

This commit is contained in:
Andrea Giammarchi
2023-09-19 18:10:46 +02:00
committed by GitHub
parent e8d5138cfa
commit f6decfd93d
7 changed files with 59 additions and 16 deletions

View File

@@ -1,12 +1,12 @@
{
"name": "@pyscript/core",
"version": "0.1.21",
"version": "0.1.22",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@pyscript/core",
"version": "0.1.21",
"version": "0.1.22",
"license": "APACHE-2.0",
"dependencies": {
"@ungap/with-resolvers": "^0.1.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@pyscript/core",
"version": "0.1.21",
"version": "0.1.22",
"type": "module",
"description": "PyScript",
"module": "./index.js",

View File

@@ -9,6 +9,7 @@ import { queryTarget } from "../node_modules/polyscript/esm/script-handler.js";
import { dedent, dispatch } from "../node_modules/polyscript/esm/utils.js";
import { Hook } from "../node_modules/polyscript/esm/worker/hooks.js";
import { ErrorCode } from "./exceptions.js";
import sync from "./sync.js";
import stdlib from "./stdlib.js";
import { config, plugins, error } from "./config.js";
@@ -40,6 +41,36 @@ const after = () => {
delete document.currentScript;
};
/**
* Some content that might contain Python/JS comments only.
* @param {string} text some content to evaluate
* @returns {boolean}
*/
const hasCommentsOnly = (text) =>
!text
.replace(/\/\*[\s\S]*?\*\//g, "")
.replace(/^\s*(?:\/\/|#).*/gm, "")
.trim();
/**
*
* @param {Element} scriptOrPyScript the element with possible `src` or `worker` content
* @returns {boolean}
*/
const hasAmbiguousContent = (
io,
{ localName, textContent, attributes: { src, worker } },
) => {
// any `src` or a non-empty `worker` attribute + not just comments
if ((src || worker?.value) && !hasCommentsOnly(textContent)) {
io.stderr(
`(${ErrorCode.CONFLICTING_CODE}) a ${localName} tag has content shadowed by attributes`,
);
return true;
}
return false;
};
/**
* Given a generic DOM Element, tries to fetch the 'src' attribute, if present.
* It either throws an error if the 'src' can't be fetched or it returns a fallback
@@ -172,6 +203,7 @@ error ||
callback(pyodide, element);
if (isScript(element)) {
if (hasAmbiguousContent(pyodide.io, element)) return;
const {
attributes: { async: isAsync, target },
} = element;
@@ -222,6 +254,7 @@ class PyScriptElement extends HTMLElement {
if (!this.executed) {
this.executed = true;
const { io, run, runAsync } = await this._pyodide.promise;
if (hasAmbiguousContent(io, this)) return;
const runner = this.hasAttribute("async") ? runAsync : run;
this.srcCode = await fetchSource(this, io, !this.childElementCount);
this.replaceChildren();

View File

@@ -7,19 +7,20 @@ const CLOSEBUTTON =
*/
export const ErrorCode = {
GENERIC: "PY0000", // Use this only for development then change to a more specific error code
FETCH_ERROR: "PY0001",
FETCH_NAME_ERROR: "PY0002",
// Currently these are created depending on error code received from fetching
FETCH_UNAUTHORIZED_ERROR: "PY0401",
FETCH_FORBIDDEN_ERROR: "PY0403",
FETCH_NOT_FOUND_ERROR: "PY0404",
FETCH_SERVER_ERROR: "PY0500",
FETCH_UNAVAILABLE_ERROR: "PY0503",
CONFLICTING_CODE: "PY0409",
BAD_CONFIG: "PY1000",
MICROPIP_INSTALL_ERROR: "PY1001",
BAD_PLUGIN_FILE_EXTENSION: "PY2000",
NO_DEFAULT_EXPORT: "PY2001",
TOP_LEVEL_AWAIT: "PY9000",
// Currently these are created depending on error code received from fetching
FETCH_ERROR: "PY0001",
FETCH_NAME_ERROR: "PY0002",
FETCH_UNAUTHORIZED_ERROR: "PY0401",
FETCH_FORBIDDEN_ERROR: "PY0403",
FETCH_NOT_FOUND_ERROR: "PY0404",
FETCH_SERVER_ERROR: "PY0500",
FETCH_UNAVAILABLE_ERROR: "PY0503",
};
export class UserError extends Error {

View File

@@ -14,5 +14,9 @@
print(4, 5, 6)
second()
</py-script>
<py-script src="whatever.py">
print(4, 5, 6)
second()
</py-script>
</head>
</html>

View File

@@ -15,5 +15,9 @@
print(4, 5, 6)
second()
</py-script>
<py-script src="whatever.py">
print(4, 5, 6)
second()
</py-script>
</head>
</html>

View File

@@ -1,6 +1,12 @@
export function _createAlertBanner(message: any, level: any, messageType?: string, logMessage?: boolean): void;
export namespace ErrorCode {
let GENERIC: string;
let CONFLICTING_CODE: string;
let BAD_CONFIG: string;
let MICROPIP_INSTALL_ERROR: string;
let BAD_PLUGIN_FILE_EXTENSION: string;
let NO_DEFAULT_EXPORT: string;
let TOP_LEVEL_AWAIT: string;
let FETCH_ERROR: string;
let FETCH_NAME_ERROR: string;
let FETCH_UNAUTHORIZED_ERROR: string;
@@ -8,11 +14,6 @@ export namespace ErrorCode {
let FETCH_NOT_FOUND_ERROR: string;
let FETCH_SERVER_ERROR: string;
let FETCH_UNAVAILABLE_ERROR: string;
let BAD_CONFIG: string;
let MICROPIP_INSTALL_ERROR: string;
let BAD_PLUGIN_FILE_EXTENSION: string;
let NO_DEFAULT_EXPORT: string;
let TOP_LEVEL_AWAIT: string;
}
export class UserError extends Error {
constructor(errorCode: any, message?: string, messageType?: string);