Skip to content

Commit

Permalink
feat(log): add debug mode
Browse files Browse the repository at this point in the history
  • Loading branch information
Pkcarreno committed Oct 11, 2024
1 parent 798d1c9 commit c3f1765
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Label } from '@/components/ui/label';
import { Switch } from '@/components/ui/switch';
import { useSettingsStore } from '@/features/editor/stores/settings';

export const DebugModeSettings = () => {
const { debugMode, updateDebugMode } = useSettingsStore();

return (
<div className="grid gap-2">
<div className="flex items-center justify-between gap-2">
<Label>Logs</Label>
<Switch onCheckedChange={updateDebugMode} checked={debugMode} />
</div>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { DebugModeSettings } from './debug-mode-settings';

export const DevelopmentSettings = () => {
return (
<div className="grid gap-4">
<h3 className="font-medium leading-none">Development</h3>
<small className="text-muted text-sm">
<b>Note:</b> These settings are intended for debugging purpose
</small>
<DebugModeSettings />
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
} from '@/components/ui/dialog';
import { Separator } from '@/components/ui/separator';

import { DevelopmentSettings } from './development';
import { EditorSettings } from './editor';
import { RuntimeSettings } from './runtime-settings';

Expand Down Expand Up @@ -51,6 +52,8 @@ export const SettingsDialogProvider: React.FC<Props> = ({ children }) => {
<RuntimeSettings />
<Separator />
<EditorSettings />
<Separator />
<DevelopmentSettings />
</DialogContent>
</Dialog>
</SettingsDialogContext.Provider>
Expand Down
6 changes: 6 additions & 0 deletions src/features/editor/stores/settings/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface SettingsState {
layout_direction: PanelGroupProps['direction'];
isFirstTime: boolean;
vimMode: boolean;
debugMode: boolean;
updateAutoRun: (value: boolean) => void;
updateAutoRunTimeout: (value: number) => void;
updateLoopSafeguardThreshold: (value: number) => void;
Expand All @@ -21,6 +22,7 @@ export interface SettingsState {
updateLayoutDirection: (value: PanelGroupProps['direction']) => void;
updateIsFirstTime: (value: boolean) => void;
updateVimMode: (value: boolean) => void;
updateDebugMode: (value: boolean) => void;
}

const _useSettingsStore = create<SettingsState>()(
Expand All @@ -34,6 +36,7 @@ const _useSettingsStore = create<SettingsState>()(
layout_direction: 'horizontal',
isFirstTime: true,
vimMode: false,
debugMode: false,
updateAutoRun: (value) => set({ auto_run: value }),
updateAutoRunTimeout: (value) => set({ auto_run_timeout: value }),
updateLoopSafeguardThreshold: (value) =>
Expand All @@ -44,13 +47,15 @@ const _useSettingsStore = create<SettingsState>()(
updateLayoutDirection: (value) => set({ layout_direction: value }),
updateIsFirstTime: (value) => set({ isFirstTime: value }),
updateVimMode: (value) => set({ vimMode: value }),
updateDebugMode: (value) => set({ debugMode: value }),
}),
{
name: 'settings-storage',
version: 1,
migrate: (persistedState, version) => {
if (version === 0) {
(persistedState as SettingsState).vimMode = false;
(persistedState as SettingsState).debugMode = false;
(persistedState as SettingsState).loop_safeguard_threshold = 1000;
}

Expand All @@ -66,3 +71,4 @@ export const SettingsLoopSafeguardThreshold = () =>
_useSettingsStore.getState().loop_safeguard_threshold;
export const SettingsLoopSafeguardTimeout = () =>
_useSettingsStore.getState().loop_safeguard_timeout;
export const SettingsDebugMode = () => _useSettingsStore.getState().debugMode;
1 change: 1 addition & 0 deletions src/features/editor/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export type remoteControlerOutsideWorker =

export type remoteControlerInsideWorkerOptions = {
loopThreshold: number;
debugMode: boolean;
};

export type remoteControlerInsideWorker =
Expand Down
5 changes: 5 additions & 0 deletions src/features/editor/utils/debug.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const DebugLog = (...args: unknown[]) => {
console.debug('DEBUG: ', ...args);
};

export const DebugLogVoid = (..._: unknown[]) => {};
18 changes: 16 additions & 2 deletions src/features/editor/utils/engine/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,22 @@ import type {

import { appendLogs } from '../../stores/editor';
import {
SettingsDebugMode,
SettingsLoopSafeguardThreshold,
SettingsLoopSafeguardTimeout,
} from '../../stores/settings';
import { DebugLog, DebugLogVoid } from '../debug';

let workerRef: Worker | undefined = undefined;
let timeoutIdRef: ReturnType<typeof setInterval> | undefined = undefined;
let DEBUG = DebugLogVoid;

const workerPostMessage: () => (params: remoteControlerInsideWorker) => void =
() => (params) =>
workerRef && (workerRef as Worker).postMessage(params);

export function stopJs() {
DEBUG('stop execution');
if (workerRef) {
workerPostMessage()({ command: 'dispose' });
workerRef.terminate();
Expand All @@ -30,8 +34,12 @@ export function stopJs() {
return true;
}

// eslint-disable-next-line max-lines-per-function
export function runJs(code: string) {
const startTime = Date.now();
const debugMode = SettingsDebugMode();

DEBUG = debugMode ? DebugLog : DebugLogVoid;

return new Promise((resolve, reject) => {
const worker = new Worker(
Expand Down Expand Up @@ -80,7 +88,12 @@ export function runJs(code: string) {
logger(data.data);
break;
case 'error':
console.log('data:', data.data, 'duration:', data.duration);
DEBUG(
'returning error. data:',
data.data,
'duration:',
data.duration,
);
logError(data.data, data.duration);
stopJs();
reject(data.data);
Expand All @@ -92,12 +105,13 @@ export function runJs(code: string) {
}
};

console.log('apunto de ejecutar al worker');
DEBUG('Start Execution');
workerPostMessage()({
command: 'run',
code: code,
options: {
loopThreshold: SettingsLoopSafeguardThreshold(),
debugMode,
},
});
});
Expand Down
11 changes: 11 additions & 0 deletions src/features/editor/utils/engine/execution-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ import type {
SystemError,
} from '@/features/editor/types';

import { DebugLog, DebugLogVoid } from '../debug';
import { rfdc } from './../rfdc';
import { disposeQuickJS, executeCode } from './runtime';

let startTimeRef: number | undefined;
let DEBUG = DebugLogVoid;

const startTimer = () => {
startTimeRef = Date.now();
Expand Down Expand Up @@ -85,6 +87,7 @@ const exposeGlobals = {
URL: UrlHandler,
};

// eslint-disable-next-line max-lines-per-function
self.onmessage = async function ({
data,
}: {
Expand All @@ -94,28 +97,33 @@ self.onmessage = async function ({
case 'run':
try {
const userCode = data.code;
DEBUG = data.options.debugMode ? DebugLog : DebugLogVoid;
if (userCode.trim().length > 0) {
const evaluationResult = await executeCode({
code: userCode.trim(),
options: {
exposeGlobals: exposeGlobals,
startTimer: startTimer,
loopThreshold: data.options.loopThreshold,
debugMode: data.options.debugMode,
},
});

switch (evaluationResult.status) {
case 'success':
DEBUG('execution successful');
postMessage({ command: 'result', data: evaluationResult.data });
break;
case 'error':
DEBUG('execution failed');
postMessage({
command: 'error',
data: evaluationResult.data,
duration: getTimeSinceExecutionBegan(),
});
break;
default:
DEBUG('execution failed: unknown error');
postMessage({
command: 'error',
data: 'evaluation response unhandled',
Expand All @@ -124,6 +132,7 @@ self.onmessage = async function ({
break;
}
} else {
DEBUG('No code to be executed');
postMessage({
command: 'error',
data: 'There is no code that can be evaluated.',
Expand All @@ -142,9 +151,11 @@ self.onmessage = async function ({
}
break;
case 'dispose':
DEBUG('dispose worker order');
disposeQuickJS();
break;
default:
DEBUG('unknown command');
postMessage({ command: 'error', data: 'Not valid execution command.' });
break;
}
Expand Down
20 changes: 13 additions & 7 deletions src/features/editor/utils/engine/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ import type {
remoteControlerInsideWorkerOptions,
SystemError,
} from '../../types';
import { DebugLog, DebugLogVoid } from '../debug';
import { getQuickJS } from '../quick-js';

let arenaRef: Arena;
let ctxRef: QuickJSContext;

let DEBUG = DebugLogVoid;

export const disposeQuickJS = () => {
console.log('dispose arena and ctx');
DEBUG('dispose arena and ctx');
if (arenaRef) {
arenaRef.dispose();
}
Expand Down Expand Up @@ -74,11 +77,13 @@ interface executeCodeProps {
export const executeCode: (
data: executeCodeProps,
) => Promise<executeCodeOutputTypes> = async ({ code, options }) => {
const { exposeGlobals, startTimer, loopThreshold } = options;
const { exposeGlobals, startTimer, loopThreshold, debugMode } = options;

DEBUG = debugMode ? DebugLog : DebugLogVoid;

return new Promise(async (resolve, reject) => {
try {
console.log('start eval');
DEBUG('start eval');
const ctx = await getQuickJS().then((deps) => {
return deps.newContext();
});
Expand All @@ -90,6 +95,7 @@ export const executeCode: (
ctx.runtime.setMemoryLimit(1024 * 640);
ctx.runtime.setMaxStackSize(1024 * 320);
ctx.runtime.setInterruptHandler(() => {
DEBUG('interrupt handler triggered. time: ', interruptCycles);
return ++interruptCycles > loopThreshold;
});

Expand All @@ -98,20 +104,20 @@ export const executeCode: (
});
arenaRef = arena;

console.log('expose functions');
DEBUG('expose functions');
arena.expose(exposeGlobals);

console.log('eval the code');
DEBUG('eval the code');
startTimer();
const result = await arena.evalCode(code);

console.log('execute pending jobs');
DEBUG('execute pending jobs');
arena.executePendingJobs();

let error = undefined;
let success = undefined;

console.log('check output status', result);
DEBUG('check output status', result);
if (result) {
if (result.error) {
error = ctx.dump(result.error);
Expand Down

0 comments on commit c3f1765

Please sign in to comment.