wip fix error

This commit is contained in:
Rizky 2023-12-03 11:28:35 +07:00
parent 3c025dae19
commit c388eba4b7
5 changed files with 214 additions and 108 deletions

View File

@ -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;
}
};

View File

@ -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);

View File

@ -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}
/>
);
} }
} }

View File

@ -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,40 +60,41 @@ 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 = {};
} }
@ -132,11 +163,7 @@ export const ViewMetaScript: FC<{
}, },
useEffect: useEffect, useEffect: useEffect,
render: (jsx: ReactNode) => { render: (jsx: ReactNode) => {
output.jsx = ( output.jsx = jsx;
<ErrorBox>
<Suspense>{jsx}</Suspense>
</ErrorBox>
);
renderLimit[v.current.page_id][item.id].cache = output.jsx; renderLimit[v.current.page_id][item.id].cache = output.jsx;
}, },
}; };
@ -157,15 +184,5 @@ export const ViewMetaScript: FC<{
}); });
} }
return output.jsx; 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`);
}
} }
}; };

View File

@ -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;