wip fix error
This commit is contained in:
parent
3c025dae19
commit
c388eba4b7
|
|
@ -1,13 +1,75 @@
|
||||||
|
import { Doc } from "yjs";
|
||||||
|
import { MContent } from "../../../../web/src/utils/types/general";
|
||||||
|
import { MItem } from "../../../../web/src/utils/types/item";
|
||||||
|
import { MRoot } from "../../../../web/src/utils/types/root";
|
||||||
import { SAction } from "../actions";
|
import { SAction } from "../actions";
|
||||||
|
import { docs } from "../entity/docs";
|
||||||
|
import { gunzipAsync } from "../entity/zlib";
|
||||||
import { SyncConnection } from "../type";
|
import { SyncConnection } from "../type";
|
||||||
|
import { transform } from "esbuild";
|
||||||
|
const decoder = new TextDecoder();
|
||||||
export const code_edit: SAction["code"]["edit"] = async function (
|
export const code_edit: SAction["code"]["edit"] = async function (
|
||||||
this: SyncConnection,
|
this: SyncConnection,
|
||||||
arg
|
arg
|
||||||
) {
|
) {
|
||||||
if (arg.type === 'adv') {
|
if (arg.type === "adv") {
|
||||||
const { item_id, mode, comp_id, page_id } = arg;
|
const { item_id, mode, comp_id, page_id, value } = arg;
|
||||||
|
const src = decoder.decode(await gunzipAsync(value));
|
||||||
|
|
||||||
|
let root = undefined as undefined | MRoot | MItem;
|
||||||
|
let doc = undefined as undefined | Doc;
|
||||||
|
if (page_id) {
|
||||||
|
const ref = docs.page[page_id];
|
||||||
|
if (ref) {
|
||||||
|
root = ref.doc.getMap("map").get("root");
|
||||||
|
doc = ref.doc as Doc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (root) {
|
||||||
|
const mitem = findId(root, item_id);
|
||||||
|
|
||||||
|
if (mitem) {
|
||||||
|
const adv = mitem.get("adv");
|
||||||
|
|
||||||
|
if (adv) {
|
||||||
|
doc?.transact(async () => {
|
||||||
|
adv.set(mode, src);
|
||||||
|
|
||||||
|
if (mode === "js") {
|
||||||
|
const res = await transform(`render(${src})`, {
|
||||||
|
jsx: "transform",
|
||||||
|
format: "cjs",
|
||||||
|
loader: "tsx",
|
||||||
|
minify: true,
|
||||||
|
sourcemap: "inline",
|
||||||
|
});
|
||||||
|
adv.set("jsBuilt", res.code);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const findId = (mitem: MContent | MRoot, id: string) => {
|
||||||
|
if ((mitem as MItem).get("id") === id) {
|
||||||
|
return mitem as MItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
const childs = (mitem as MItem).get("childs");
|
||||||
|
if (childs) {
|
||||||
|
let found: null | MItem = null;
|
||||||
|
childs.forEach((child) => {
|
||||||
|
const f = findId(child, id);
|
||||||
|
if (f) {
|
||||||
|
found = f;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (found) return found;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -153,15 +153,24 @@ export const ScriptMonaco = () => {
|
||||||
{ css: "scss", js: "typescript", html: "html" }[p.ui.popup.script.mode]
|
{ css: "scss", js: "typescript", html: "html" }[p.ui.popup.script.mode]
|
||||||
}
|
}
|
||||||
onChange={(val) => {
|
onChange={(val) => {
|
||||||
|
clearTimeout(scriptEdit.timeout);
|
||||||
scriptEdit.timeout = setTimeout(() => {
|
scriptEdit.timeout = setTimeout(() => {
|
||||||
const meta = getMetaById(p, active.item_id);
|
const meta = getMetaById(p, active.item_id);
|
||||||
const type = p.ui.popup.script.mode;
|
const type = p.ui.popup.script.mode;
|
||||||
if (meta && meta.mitem) {
|
if (meta && meta.mitem) {
|
||||||
|
let arg = {} as any;
|
||||||
|
if (active.comp_id) {
|
||||||
|
arg.comp_id = active.comp_id;
|
||||||
|
} else {
|
||||||
|
arg.page_id = p.page.cur.id;
|
||||||
|
}
|
||||||
|
|
||||||
p.sync.code.edit({
|
p.sync.code.edit({
|
||||||
type: "adv",
|
type: "adv",
|
||||||
mode: type,
|
mode: type,
|
||||||
item_id: active.item_id,
|
item_id: active.item_id,
|
||||||
value: compress(encode.encode(val || "")),
|
value: compress(encode.encode(val || "")),
|
||||||
|
...arg,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,9 @@ import { FC, useState } from "react";
|
||||||
import { useGlobal } from "web-utils";
|
import { useGlobal } from "web-utils";
|
||||||
import { ViewGlobal } from "../../logic/global";
|
import { ViewGlobal } from "../../logic/global";
|
||||||
import { ViewMetaRender } from "./render";
|
import { ViewMetaRender } from "./render";
|
||||||
import { ViewMetaScript } from "./script";
|
import { ViewBoundedScript, ViewMetaScript } from "./script";
|
||||||
import { compPropVal } from "./script/comp-propval";
|
import { compPropVal } from "./script/comp-propval";
|
||||||
|
import { ErrorBox } from "./script/error-box";
|
||||||
|
|
||||||
export const ViewMeta: FC<{ id: string; scopeIndex?: Record<string, any> }> = ({
|
export const ViewMeta: FC<{ id: string; scopeIndex?: Record<string, any> }> = ({
|
||||||
id,
|
id,
|
||||||
|
|
@ -30,8 +31,15 @@ export const ViewMeta: FC<{ id: string; scopeIndex?: Record<string, any> }> = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.adv) {
|
if (item.adv) {
|
||||||
if (item.adv.js && item.adv.jsBuilt) {
|
if (item.adv.js && item.adv.jsBuilt && typeof item.adv.js === "string") {
|
||||||
return <ViewMetaScript v={v} item={item} scopeIndex={scopeIndex} />;
|
return (
|
||||||
|
<ViewBoundedScript
|
||||||
|
js={item.adv.js}
|
||||||
|
v={v}
|
||||||
|
item={item}
|
||||||
|
scopeIndex={scopeIndex}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,39 @@ import { createLocal } from "./script/create-local";
|
||||||
import { createPassProp } from "./script/create-pass-prop";
|
import { createPassProp } from "./script/create-pass-prop";
|
||||||
import { ErrorBox } from "./script/error-box";
|
import { ErrorBox } from "./script/error-box";
|
||||||
import { mergeScopeUpwards } from "./script/merge-upward";
|
import { mergeScopeUpwards } from "./script/merge-upward";
|
||||||
|
import { useLocal } from "web-utils";
|
||||||
|
|
||||||
|
const renderLimit = {} as Record<
|
||||||
|
string,
|
||||||
|
Record<string, { ts: number; count: number; cache: ReactNode }>
|
||||||
|
>;
|
||||||
|
|
||||||
|
export const ViewBoundedScript: FC<{
|
||||||
|
v: VG;
|
||||||
|
item: IItem | IText | ISection;
|
||||||
|
scopeIndex?: Record<string, any>;
|
||||||
|
js: string;
|
||||||
|
}> = ({ item, v, scopeIndex, js }) => {
|
||||||
|
const local = useLocal({ js: "" });
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (local.js !== js) {
|
||||||
|
local.js = js;
|
||||||
|
local.render();
|
||||||
|
}
|
||||||
|
}, [js]);
|
||||||
|
|
||||||
|
if (local.js !== js) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ErrorBox silent={true}>
|
||||||
|
<ViewMetaScript v={v} item={item} scopeIndex={scopeIndex} />
|
||||||
|
</ErrorBox>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const renderLimit = {} as Record<string, Record<string, { ts: number, count: number; cache: ReactNode }>>;
|
|
||||||
export const ViewMetaScript: FC<{
|
export const ViewMetaScript: FC<{
|
||||||
v: VG;
|
v: VG;
|
||||||
item: IItem | IText | ISection;
|
item: IItem | IText | ISection;
|
||||||
|
|
@ -30,142 +60,129 @@ export const ViewMetaScript: FC<{
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!renderLimit[v.current.page_id]) {
|
if (!renderLimit[v.current.page_id]) {
|
||||||
renderLimit[v.current.page_id] = {}
|
renderLimit[v.current.page_id] = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!renderLimit[v.current.page_id][item.id]) {
|
if (!renderLimit[v.current.page_id][item.id]) {
|
||||||
renderLimit[v.current.page_id][item.id] = {
|
renderLimit[v.current.page_id][item.id] = {
|
||||||
ts: Date.now(),
|
ts: Date.now(),
|
||||||
count: 1,
|
count: 1,
|
||||||
cache: null
|
cache: null,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (renderLimit[v.current.page_id][item.id].ts - Date.now() < 100) {
|
if (renderLimit[v.current.page_id][item.id].ts - Date.now() < 100) {
|
||||||
renderLimit[v.current.page_id][item.id].count++
|
renderLimit[v.current.page_id][item.id].count++;
|
||||||
} else {
|
} else {
|
||||||
renderLimit[v.current.page_id][item.id].ts = Date.now();
|
renderLimit[v.current.page_id][item.id].ts = Date.now();
|
||||||
renderLimit[v.current.page_id][item.id].count = 1;
|
renderLimit[v.current.page_id][item.id].count = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (renderLimit[v.current.page_id][item.id].count > 100) {
|
if (renderLimit[v.current.page_id][item.id].count > 100) {
|
||||||
|
let js = "";
|
||||||
let js = '';
|
if (typeof item.adv?.js === "string") {
|
||||||
if (typeof item.adv?.js === 'string') {
|
|
||||||
js = item.adv.js;
|
js = item.adv.js;
|
||||||
}
|
}
|
||||||
console.warn(`Maximum render limit (100 render in 100ms) reached in item [${item.name}]:\n${js.length > 30 ? js.substring(0, 30) + '...' : js}`)
|
console.warn(
|
||||||
|
`Maximum render limit (100 render in 100ms) reached in item [${
|
||||||
|
item.name
|
||||||
|
}]:\n${js.length > 30 ? js.substring(0, 30) + "..." : js}`
|
||||||
|
);
|
||||||
return renderLimit[v.current.page_id][item.id].cache;
|
return renderLimit[v.current.page_id][item.id].cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const children = <ViewMetaChildren key={item.id} meta={meta} />;
|
const children = <ViewMetaChildren key={item.id} meta={meta} />;
|
||||||
let args = {};
|
let args = {};
|
||||||
|
|
||||||
if (js && meta) {
|
if (js && meta) {
|
||||||
try {
|
if (!meta.memoize) {
|
||||||
if (!meta.memoize) {
|
meta.memoize = {};
|
||||||
meta.memoize = {};
|
}
|
||||||
}
|
const memoizeKey = hash_sum(scopeIndex) || "default";
|
||||||
const memoizeKey = hash_sum(scopeIndex) || "default";
|
if (!meta.memoize[memoizeKey]) {
|
||||||
if (!meta.memoize[memoizeKey]) {
|
meta.memoize[memoizeKey] = {
|
||||||
meta.memoize[memoizeKey] = {
|
Local: createLocal(v, item.id, scopeIndex),
|
||||||
Local: createLocal(v, item.id, scopeIndex),
|
PassProp: createPassProp(v, item.id, scopeIndex),
|
||||||
PassProp: createPassProp(v, item.id, scopeIndex),
|
};
|
||||||
};
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const _js = item.adv?.js;
|
const _js = item.adv?.js;
|
||||||
if (typeof _js === "string") {
|
if (typeof _js === "string") {
|
||||||
const navs = extractNavigate(_js || "");
|
const navs = extractNavigate(_js || "");
|
||||||
if (navs.length > 0) {
|
if (navs.length > 0) {
|
||||||
navs.map((nav) => preload(v, nav));
|
navs.map((nav) => preload(v, nav));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v.script.api_url) {
|
||||||
|
if (!v.script.db) v.script.db = createDB(v.script.api_url);
|
||||||
|
if (!v.script.api) v.script.api = createAPI(v.script.api_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
const finalScope = mergeScopeUpwards(v, item.id, scopeIndex);
|
||||||
|
for (const [k, v] of Object.entries(finalScope)) {
|
||||||
|
if (v && typeof v === "object") {
|
||||||
|
const t: {
|
||||||
|
_jsx: true;
|
||||||
|
Comp: FC<{ parent_id: string; scopeIndex?: Record<string, any> }>;
|
||||||
|
} = v as any;
|
||||||
|
if (t._jsx && t.Comp) {
|
||||||
|
finalScope[k] = (
|
||||||
|
<>
|
||||||
|
<t.Comp parent_id={meta.item.id} scopeIndex={scopeIndex} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
const output = { jsx: null as any };
|
||||||
|
|
||||||
if (v.script.api_url) {
|
args = {
|
||||||
if (!v.script.db) v.script.db = createDB(v.script.api_url);
|
...w.exports,
|
||||||
if (!v.script.api) v.script.api = createAPI(v.script.api_url);
|
...finalScope,
|
||||||
}
|
...meta.memoize[memoizeKey],
|
||||||
|
db: v.script.db,
|
||||||
const finalScope = mergeScopeUpwards(v, item.id, scopeIndex);
|
api: v.script.api,
|
||||||
for (const [k, v] of Object.entries(finalScope)) {
|
children,
|
||||||
if (v && typeof v === "object") {
|
props: {
|
||||||
const t: {
|
className,
|
||||||
_jsx: true;
|
onPointerOver: v.view.hover
|
||||||
Comp: FC<{ parent_id: string; scopeIndex?: Record<string, any> }>;
|
? (e: any) => {
|
||||||
} = v as any;
|
|
||||||
if (t._jsx && t.Comp) {
|
|
||||||
finalScope[k] = (
|
|
||||||
<>
|
|
||||||
<t.Comp parent_id={meta.item.id} scopeIndex={scopeIndex} />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const output = { jsx: null as any };
|
|
||||||
|
|
||||||
args = {
|
|
||||||
...w.exports,
|
|
||||||
...finalScope,
|
|
||||||
...meta.memoize[memoizeKey],
|
|
||||||
db: v.script.db,
|
|
||||||
api: v.script.api,
|
|
||||||
children,
|
|
||||||
props: {
|
|
||||||
className,
|
|
||||||
onPointerOver: v.view.hover
|
|
||||||
? (e: any) => {
|
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
v.view.hover?.set(meta);
|
v.view.hover?.set(meta);
|
||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
onClick: v.view.active
|
onClick: v.view.active
|
||||||
? (e: any) => {
|
? (e: any) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
v.view.active?.set(meta);
|
v.view.active?.set(meta);
|
||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
},
|
},
|
||||||
useEffect: useEffect,
|
useEffect: useEffect,
|
||||||
render: (jsx: ReactNode) => {
|
render: (jsx: ReactNode) => {
|
||||||
output.jsx = (
|
output.jsx = jsx;
|
||||||
<ErrorBox>
|
renderLimit[v.current.page_id][item.id].cache = output.jsx;
|
||||||
<Suspense>{jsx}</Suspense>
|
},
|
||||||
</ErrorBox>
|
};
|
||||||
);
|
|
||||||
renderLimit[v.current.page_id][item.id].cache = output.jsx;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// execute
|
// execute
|
||||||
const fn = new Function(...Object.keys(args), js);
|
const fn = new Function(...Object.keys(args), js);
|
||||||
const res = fn(...Object.values(args));
|
const res = fn(...Object.values(args));
|
||||||
if (res instanceof Promise) {
|
if (res instanceof Promise) {
|
||||||
res.catch((e: any) => {
|
res.catch((e: any) => {
|
||||||
console.warn(e);
|
console.warn(e);
|
||||||
console.warn(
|
console.warn(
|
||||||
(
|
(
|
||||||
`ERROR in ${item.type} [${item.name}]:\n ` +
|
`ERROR in ${item.type} [${item.name}]:\n ` +
|
||||||
((item.adv?.js || "") as any)
|
((item.adv?.js || "") as any)
|
||||||
).trim()
|
).trim()
|
||||||
);
|
);
|
||||||
console.warn(`Available var:`, args, `\n\n`);
|
console.warn(`Available var:`, args, `\n\n`);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
return output.jsx;
|
|
||||||
} catch (e) {
|
|
||||||
console.warn(e);
|
|
||||||
console.warn(
|
|
||||||
(
|
|
||||||
`ERROR in ${item.type} [${item.name}]:\n ` +
|
|
||||||
((item.adv?.js || "") as any)
|
|
||||||
).trim()
|
|
||||||
);
|
|
||||||
console.warn(`Available var:`, args, `\n\n`);
|
|
||||||
}
|
}
|
||||||
|
return output.jsx;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,20 @@ import { EdMeta } from "../../../../ed/logic/ed-global";
|
||||||
import { ViewGlobal } from "../../../logic/global";
|
import { ViewGlobal } from "../../../logic/global";
|
||||||
|
|
||||||
export const ErrorBox = withErrorBoundary(
|
export const ErrorBox = withErrorBoundary(
|
||||||
({ children, meta, id }: { children: any; meta?: EdMeta; id?: string }) => {
|
({
|
||||||
|
children,
|
||||||
|
meta,
|
||||||
|
id,
|
||||||
|
silent,
|
||||||
|
}: {
|
||||||
|
children: any;
|
||||||
|
meta?: EdMeta;
|
||||||
|
id?: string;
|
||||||
|
silent?: boolean;
|
||||||
|
}) => {
|
||||||
const local = useLocal({ retrying: false });
|
const local = useLocal({ retrying: false });
|
||||||
const [error, resetError] = useErrorBoundary((error, errorInfo) => {
|
const [error, resetError] = useErrorBoundary((error, errorInfo) => {
|
||||||
console.warn(error);
|
if (silent !== true) console.warn(error);
|
||||||
});
|
});
|
||||||
|
|
||||||
let _meta = meta;
|
let _meta = meta;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue