Getting the line number calculated correctly, as well as adding some basic test cases.
This commit is contained in:
parent
7efe88dfda
commit
e6d536bcc8
|
@ -102,7 +102,7 @@
|
||||||
<!-- eslint-disable-next-line svelte/no-at-html-tags-->
|
<!-- eslint-disable-next-line svelte/no-at-html-tags-->
|
||||||
<span>{@html logLine.log}</span>
|
<span>{@html logLine.log}</span>
|
||||||
{#if logLine.line}
|
{#if logLine.line}
|
||||||
<span style="color: var(--blue)">line {logLine.line}</span>
|
<span style="color: var(--blue)">:{logLine.line}</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
import { atob, isBackendService, isJSAllowed } from "../utilities"
|
import {
|
||||||
|
atob,
|
||||||
|
frontendWrapJS,
|
||||||
|
isBackendService,
|
||||||
|
isJSAllowed,
|
||||||
|
} from "../utilities"
|
||||||
import { LITERAL_MARKER } from "../helpers/constants"
|
import { LITERAL_MARKER } from "../helpers/constants"
|
||||||
import { getJsHelperList } from "./list"
|
import { getJsHelperList } from "./list"
|
||||||
import { iifeWrapper } from "../iife"
|
import { iifeWrapper } from "../iife"
|
||||||
|
@ -117,7 +122,21 @@ export function processJS(handlebars: string, context: any) {
|
||||||
const logs: Log[] = []
|
const logs: Log[] = []
|
||||||
// logging only supported on frontend
|
// logging only supported on frontend
|
||||||
if (!isBackendService()) {
|
if (!isBackendService()) {
|
||||||
const log = (log: string) => logs.push({ log })
|
// this counts the lines in the wrapped JS *before* the user's code, so that we can minus it
|
||||||
|
const jsLineCount = frontendWrapJS(js).split(js)[0].split("\n").length
|
||||||
|
const log = (log: string) => {
|
||||||
|
// quick way to find out what line this is being called from
|
||||||
|
// its an anonymous function and we look for the overall length to find the
|
||||||
|
// line number we care about (from the users function)
|
||||||
|
// JS stack traces are in the format function:line:column
|
||||||
|
const lineNumber = new Error().stack?.match(
|
||||||
|
/<anonymous>:(\d+):\d+/
|
||||||
|
)?.[1]
|
||||||
|
logs.push({
|
||||||
|
log,
|
||||||
|
line: lineNumber ? parseInt(lineNumber) - jsLineCount : undefined,
|
||||||
|
})
|
||||||
|
}
|
||||||
sandboxContext.console = {
|
sandboxContext.console = {
|
||||||
log: log,
|
log: log,
|
||||||
info: log,
|
info: log,
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {
|
||||||
FIND_ANY_HBS_REGEX,
|
FIND_ANY_HBS_REGEX,
|
||||||
FIND_HBS_REGEX,
|
FIND_HBS_REGEX,
|
||||||
findDoubleHbsInstances,
|
findDoubleHbsInstances,
|
||||||
|
frontendWrapJS,
|
||||||
isBackendService,
|
isBackendService,
|
||||||
prefixStrings,
|
prefixStrings,
|
||||||
} from "./utilities"
|
} from "./utilities"
|
||||||
|
@ -511,20 +512,7 @@ export function browserJSSetup() {
|
||||||
setJSRunner((js: string, context: Record<string, any>) => {
|
setJSRunner((js: string, context: Record<string, any>) => {
|
||||||
createContext(context)
|
createContext(context)
|
||||||
|
|
||||||
const wrappedJs = `
|
const wrappedJs = frontendWrapJS(js)
|
||||||
result = {
|
|
||||||
result: null,
|
|
||||||
error: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
result.result = ${js};
|
|
||||||
} catch (e) {
|
|
||||||
result.error = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
result;
|
|
||||||
`
|
|
||||||
|
|
||||||
const result = runInNewContext(wrappedJs, context, { timeout: 1000 })
|
const result = runInNewContext(wrappedJs, context, { timeout: 1000 })
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
|
|
|
@ -86,3 +86,20 @@ export const prefixStrings = (
|
||||||
const regexPattern = new RegExp(`\\b(${escapedStrings.join("|")})\\b`, "g")
|
const regexPattern = new RegExp(`\\b(${escapedStrings.join("|")})\\b`, "g")
|
||||||
return baseString.replace(regexPattern, `${prefix}$1`)
|
return baseString.replace(regexPattern, `${prefix}$1`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function frontendWrapJS(js: string) {
|
||||||
|
return `
|
||||||
|
result = {
|
||||||
|
result: null,
|
||||||
|
error: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
result.result = ${js};
|
||||||
|
} catch (e) {
|
||||||
|
result.error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
result;
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
import {
|
||||||
|
processStringWithLogsSync,
|
||||||
|
encodeJSBinding,
|
||||||
|
defaultJSSetup,
|
||||||
|
} from "../src/index"
|
||||||
|
|
||||||
|
const processJS = (js: string, context?: object) => {
|
||||||
|
return processStringWithLogsSync(encodeJSBinding(js), context)
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("Javascript", () => {
|
||||||
|
beforeAll(() => {
|
||||||
|
defaultJSSetup()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("Test logging in JS bindings", () => {
|
||||||
|
it("should execute a simple expression", () => {
|
||||||
|
const output = processJS(
|
||||||
|
`console.log("hello");
|
||||||
|
console.log("world");
|
||||||
|
console.log("foo");
|
||||||
|
return "hello"`
|
||||||
|
)
|
||||||
|
expect(output.result).toBe("hello")
|
||||||
|
expect(output.logs[0].log).toBe("hello")
|
||||||
|
expect(output.logs[0].line).toBe(1)
|
||||||
|
expect(output.logs[1].log).toBe("world")
|
||||||
|
expect(output.logs[1].line).toBe(2)
|
||||||
|
expect(output.logs[2].log).toBe("foo")
|
||||||
|
expect(output.logs[2].line).toBe(3)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
Loading…
Reference in New Issue