From 555489674c6f333d0bd1fa3b5162112f3f1d8b9c Mon Sep 17 00:00:00 2001 From: Mark McCulloh Date: Fri, 26 Jan 2024 11:19:39 -0500 Subject: [PATCH 01/17] fix --- examples/tests/invalid/extern_above.test.w | 4 --- examples/tests/invalid/lib/extern_above.w | 4 +++ libs/wingc/src/jsify.rs | 40 +++++++++++++++------- libs/wingsdk/src/shared/bundling.ts | 23 ++++--------- libs/wingsdk/src/util/enhanced-error.ts | 16 ++++++++- tools/hangar/__snapshots__/invalid.ts.snap | 27 +++++++-------- tools/hangar/src/invalid.test.ts | 16 +++++++++ 7 files changed, 81 insertions(+), 49 deletions(-) delete mode 100644 examples/tests/invalid/extern_above.test.w create mode 100644 examples/tests/invalid/lib/extern_above.w diff --git a/examples/tests/invalid/extern_above.test.w b/examples/tests/invalid/extern_above.test.w deleted file mode 100644 index 44c3ae5bd5e..00000000000 --- a/examples/tests/invalid/extern_above.test.w +++ /dev/null @@ -1,4 +0,0 @@ -class Foo1 { - extern "../valid/external_js.js" static getGreeting(name: str): str; - //^ must be a sub directory of the entrypoint -} diff --git a/examples/tests/invalid/lib/extern_above.w b/examples/tests/invalid/lib/extern_above.w new file mode 100644 index 00000000000..ca7dde0c303 --- /dev/null +++ b/examples/tests/invalid/lib/extern_above.w @@ -0,0 +1,4 @@ +class Foo1 { + extern "../../valid/external_js.js" static getGreeting(name: str): str; + //^ must be a sub directory of the entrypoint +} diff --git a/libs/wingc/src/jsify.rs b/libs/wingc/src/jsify.rs index 049b82b7211..98550f4f9f7 100644 --- a/libs/wingc/src/jsify.rs +++ b/libs/wingc/src/jsify.rs @@ -6,6 +6,7 @@ use camino::{Utf8Path, Utf8PathBuf}; use const_format::formatcp; use indexmap::{IndexMap, IndexSet}; use itertools::Itertools; +use parcel_sourcemap::utils::make_relative_path; use std::{borrow::Borrow, cell::RefCell, cmp::Ordering, collections::BTreeMap, vec}; @@ -269,7 +270,11 @@ impl<'a> JSifier<'a> { let source_content = self.source_files.get_file(source_path.as_str()).unwrap(); let output_base = output.to_string(); - let output_sourcemap = output.generate_sourcemap(source_path.as_str(), source_content, &preflight_file_name); + let output_sourcemap = output.generate_sourcemap( + &make_relative_path(self.out_dir.as_str(), source_path.as_str()), + source_content, + &preflight_file_name, + ); // Emit the file match self @@ -1300,22 +1305,30 @@ impl<'a> JSifier<'a> { FunctionBody::Statements(scope) => self.jsify_scope_body(scope, ctx), FunctionBody::External(extern_path) => { let extern_path = Utf8Path::new(extern_path); - let entrypoint_dir = if self.compilation_init_path.is_file() { + let entrypoint_is_file = self.compilation_init_path.is_file(); + let entrypoint_dir = if entrypoint_is_file { self.compilation_init_path.parent().unwrap() } else { self.compilation_init_path }; - // extern_path should always be a sub directory of entrypoint_dir - let Ok(rel_path) = extern_path.strip_prefix(&entrypoint_dir) else { - report_diagnostic(Diagnostic { - message: format!("{extern_path} must be a sub directory of {entrypoint_dir}"), - annotations: vec![], - hints: vec![], - span: Some(func_def.span.clone()), - }); - return CodeMaker::default(); - }; + if !entrypoint_is_file { + // We are possibly compiling a package, so we need to make sure all externs + // are actually contained in this directory to make sure it gets packaged + + if !extern_path.starts_with(entrypoint_dir) { + report_diagnostic(Diagnostic { + message: format!("{extern_path} must be a sub directory of {entrypoint_dir}"), + annotations: vec![], + hints: vec![], + span: Some(func_def.span.clone()), + }); + return CodeMaker::default(); + } + } + + let rel_path = make_relative_path(entrypoint_dir.as_str(), extern_path.as_str()); + let rel_path = Utf8PathBuf::from(rel_path); let mut path_components = rel_path.components(); @@ -1692,10 +1705,11 @@ impl<'a> JSifier<'a> { Ok(()) => {} Err(err) => report_diagnostic(err.into()), } + match self.output_files.borrow_mut().add_file( sourcemap_file, code.generate_sourcemap( - root_source.as_str(), + &make_relative_path(self.out_dir.as_str(), &root_source), self.source_files.get_file(root_source.as_str()).unwrap(), filename.as_str(), ), diff --git a/libs/wingsdk/src/shared/bundling.ts b/libs/wingsdk/src/shared/bundling.ts index 5de4c14e1ac..8ef0956a3a9 100644 --- a/libs/wingsdk/src/shared/bundling.ts +++ b/libs/wingsdk/src/shared/bundling.ts @@ -1,6 +1,6 @@ import * as crypto from "crypto"; import { mkdirSync, writeFileSync } from "fs"; -import { join, relative, resolve } from "path"; +import { join, resolve } from "path"; import { normalPath } from "./misc"; const SDK_PATH = normalPath(resolve(__dirname, "..", "..")); @@ -25,7 +25,6 @@ export function createBundle( external: string[] = [], outputDir?: string ): Bundle { - const originalEntrypointDir = normalPath(resolve(entrypoint, "..")); const outdir = resolve(outputDir ?? entrypoint + ".bundle"); mkdirSync(outdir, { recursive: true }); @@ -41,9 +40,7 @@ export function createBundle( let esbuild = esbuilder.buildSync({ bundle: true, entryPoints: [normalPath(resolve(entrypoint))], - outdir: originalEntrypointDir, - sourceRoot: originalEntrypointDir + "/", - absWorkingDir: originalEntrypointDir, + outfile, // otherwise there are problems with running azure cloud functions: // https://stackoverflow.com/questions/70332883/webpack-azure-storage-blob-node-fetch-abortsignal-issue keepNames: true, @@ -70,21 +67,15 @@ export function createBundle( const output = esbuild.outputFiles[1]; let fileContents = new TextDecoder().decode(output.contents); - // sourcemap hacks for winglang: - // source paths in sourcemap are incorrect and need to be fixed + // ensure source paths have posix path separators const sourcemapData = JSON.parse( new TextDecoder().decode(esbuild.outputFiles[0].contents) ); - - // ensure sourceRoot has posix path separators sourcemapData.sourceRoot = normalPath(sourcemapData.sourceRoot); - - for (const [idx, source] of Object.entries(sourcemapData.sources)) { - if ((source as any).endsWith(".w")) { - const absolutePath = `/${source}`; - const relativePath = relative(originalEntrypointDir, absolutePath); - sourcemapData.sources[idx] = relativePath; - } + for (const [idx, source] of Object.entries( + sourcemapData.sources as string[] + )) { + sourcemapData.sources[idx] = normalPath(source); } fileContents += `//# sourceMappingURL=${soucemapFilename}`; diff --git a/libs/wingsdk/src/util/enhanced-error.ts b/libs/wingsdk/src/util/enhanced-error.ts index e978490685a..3ab1ae52cf3 100644 --- a/libs/wingsdk/src/util/enhanced-error.ts +++ b/libs/wingsdk/src/util/enhanced-error.ts @@ -2,6 +2,10 @@ import { stat } from "node:fs/promises"; import { relative, resolve, sep, join } from "node:path"; import type Chalk from "chalk"; import type StackTracey from "stacktracey"; +import { normalPath } from "../shared/misc"; + +/** Resolved sources we want to remove from the pretty stack */ +const KNOWN_SOURCES_TO_STRIP = ["wingsdk/src/helpers.ts"]; export interface PrettyPrintErrorOptions { /** @@ -67,13 +71,23 @@ export async function prettyPrintError( st = await st.clean().withSourcesAsync(); - let traceWithSources = st.items.filter((item) => !item.native); + let traceWithSources = st.items + .filter((item) => !item.native) + // strip node internals + .filter((item) => !item.file.startsWith("node:internal/")) + .filter( + (item) => + !KNOWN_SOURCES_TO_STRIP.some((source) => + normalPath(item.file).endsWith(source) + ) + ); if (traceWithSources.length === 0) { return message; } let interestingRoot = options?.sourceEntrypoint; + if ( interestingRoot !== undefined && (await stat(interestingRoot) diff --git a/tools/hangar/__snapshots__/invalid.ts.snap b/tools/hangar/__snapshots__/invalid.ts.snap index 7964e0ff0c9..4b24e67dbe9 100644 --- a/tools/hangar/__snapshots__/invalid.ts.snap +++ b/tools/hangar/__snapshots__/invalid.ts.snap @@ -1252,21 +1252,6 @@ exports[`extern.test.w 1`] = ` -Tests 1 failed (1) -Test Files 1 failed (1) -Duration " -`; - -exports[`extern_above.test.w 1`] = ` -"error: /external_js.js must be a sub directory of /invalid - --> ../../../examples/tests/invalid/extern_above.test.w:2:3 - | -2 | extern \\"../valid/external_js.js\\" static getGreeting(name: str): str; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /external_js.js must be a sub directory of /invalid - - - - Tests 1 failed (1) Test Files 1 failed (1) Duration " @@ -2237,6 +2222,18 @@ Test Files 1 failed (1) Duration " `; +exports[`invalid compile directory 1`] = `""`; + +exports[`invalid compile directory 2`] = ` +"error: /external_js.js must be a sub directory of /lib + --> ../../../examples/tests/invalid/lib/extern_above.w:2:3 + | +2 | extern \\"../../valid/external_js.js\\" static getGreeting(name: str): str; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /external_js.js must be a sub directory of /lib + +" +`; + exports[`issue_2767.test.w 1`] = ` "error: Expected type to be \\"MutJson\\", but got \\"Bucket\\" instead --> ../../../examples/tests/invalid/issue_2767.test.w:4:16 diff --git a/tools/hangar/src/invalid.test.ts b/tools/hangar/src/invalid.test.ts index e105ce0a01c..b69d9414a10 100644 --- a/tools/hangar/src/invalid.test.ts +++ b/tools/hangar/src/invalid.test.ts @@ -32,3 +32,19 @@ invalidWingFiles.forEach((wingFile) => { } }); }); + +const invalidLibDir = path.join(invalidTestDir, "lib"); +test("invalid compile directory", async ({ expect }) => { + const platforms = ["sim"]; + const args = ["compile"]; + + const out = await runWingCommand({ + cwd: tmpDir, + wingFile: invalidLibDir, + platforms, + args, + expectFailure: true, + }); + + expect(out.stderr).toMatchSnapshot(); +}) \ No newline at end of file From f8b264a13a381b081bde942bf782ad930e0b3d28 Mon Sep 17 00:00:00 2001 From: Mark McCulloh Date: Fri, 26 Jan 2024 12:38:57 -0500 Subject: [PATCH 02/17] filter harder --- libs/wingsdk/src/simulator/client.ts | 7 +++++- libs/wingsdk/src/util/enhanced-error.ts | 30 +++++++++++++++---------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/libs/wingsdk/src/simulator/client.ts b/libs/wingsdk/src/simulator/client.ts index 8199dafc917..0c62eaa4b66 100644 --- a/libs/wingsdk/src/simulator/client.ts +++ b/libs/wingsdk/src/simulator/client.ts @@ -59,8 +59,13 @@ export function makeSimulatorClient(url: string, handle: string) { let err = new Error(); err.message = parsed.error?.message; - err.stack = parsed.error?.stack; err.name = parsed.error?.name; + + if (parsed.error?.stack) { + // combine the stack trace from the server with the stack trace from the client + err.stack = `${parsed.error.stack}\n${err.stack}`; + } + throw err; } diff --git a/libs/wingsdk/src/util/enhanced-error.ts b/libs/wingsdk/src/util/enhanced-error.ts index 3ab1ae52cf3..a4a4696fd6a 100644 --- a/libs/wingsdk/src/util/enhanced-error.ts +++ b/libs/wingsdk/src/util/enhanced-error.ts @@ -4,9 +4,6 @@ import type Chalk from "chalk"; import type StackTracey from "stacktracey"; import { normalPath } from "../shared/misc"; -/** Resolved sources we want to remove from the pretty stack */ -const KNOWN_SOURCES_TO_STRIP = ["wingsdk/src/helpers.ts"]; - export interface PrettyPrintErrorOptions { /** * The source entrypoint. If provided, the stack trace will only show source files that are in the same directory or its subdirectories. @@ -69,18 +66,22 @@ export async function prettyPrintError( const message = fBold(fRed("runtime error: ")) + fRed(originalMessage); - st = await st.clean().withSourcesAsync(); + console.log(st.asTable()); - let traceWithSources = st.items + st = await st + .clean() .filter((item) => !item.native) // strip node internals - .filter((item) => !item.file.startsWith("node:internal/")) - .filter( - (item) => - !KNOWN_SOURCES_TO_STRIP.some((source) => - normalPath(item.file).endsWith(source) - ) - ); + .filter((item) => !item.file.startsWith("node:")) + // strip wingsdk + .filter((item) => !normalPath(item.file).includes("/libs/wingsdk/src/")) + // special: remove the handler wrapper (See `cloud.Function` entrypoint for where this comes from) + .filter((item) => !normalPath(item.file).match(/\.wing\/handler_\w+\.js$/)) + .withSourcesAsync(); + + let traceWithSources = st.items; + + // special handling: If the bottom of the stack is a js file if (traceWithSources.length === 0) { return message; @@ -192,6 +193,11 @@ function printItem(item: StackTracey.Entry) { calleeShort = ""; } + if (item.callee.match(/\$Closure\d+\.handle$/)) { + // inflight closures use "handle" as a way to represent calling the inflight itself + calleeShort = ""; + } + const file = item.file; const line = item.line; const column = item.column; From cc2e01a9485c5a399be0f312f25f23a6c82fb563 Mon Sep 17 00:00:00 2001 From: Mark McCulloh Date: Fri, 26 Jan 2024 12:40:21 -0500 Subject: [PATCH 03/17] remove console.log --- libs/wingsdk/src/util/enhanced-error.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/libs/wingsdk/src/util/enhanced-error.ts b/libs/wingsdk/src/util/enhanced-error.ts index a4a4696fd6a..e9e79539ce4 100644 --- a/libs/wingsdk/src/util/enhanced-error.ts +++ b/libs/wingsdk/src/util/enhanced-error.ts @@ -66,8 +66,6 @@ export async function prettyPrintError( const message = fBold(fRed("runtime error: ")) + fRed(originalMessage); - console.log(st.asTable()); - st = await st .clean() .filter((item) => !item.native) From 380ce5ae0de3f8894ea01c1b7d717b11f0c642c6 Mon Sep 17 00:00:00 2001 From: Mark McCulloh Date: Fri, 26 Jan 2024 13:00:12 -0500 Subject: [PATCH 04/17] clean --- libs/wingsdk/src/util/enhanced-error.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libs/wingsdk/src/util/enhanced-error.ts b/libs/wingsdk/src/util/enhanced-error.ts index e9e79539ce4..b006d58c6fd 100644 --- a/libs/wingsdk/src/util/enhanced-error.ts +++ b/libs/wingsdk/src/util/enhanced-error.ts @@ -196,10 +196,16 @@ function printItem(item: StackTracey.Entry) { calleeShort = ""; } + if (item.fileName.endsWith(".w") && calleeShort.startsWith("async ")) { + // In userland wing traces, async = inflight and is currently redundant to mention + calleeShort = calleeShort.replace("async ", ""); + } + const file = item.file; const line = item.line; const column = item.column; - return `at ${calleeShort}(${file}:${line}:${column})`; + + return `at ${calleeShort}${file}:${line}:${column}`; } export function rewriteCommonError(error: Error): Error { From 8c1887fe0c055c11740c96eba398519fa554e186 Mon Sep 17 00:00:00 2001 From: Mark McCulloh Date: Fri, 26 Jan 2024 13:04:03 -0500 Subject: [PATCH 05/17] snaps --- tools/hangar/__snapshots__/error.ts.snap | 24 +++++++++---------- tools/hangar/__snapshots__/invalid.ts.snap | 6 ++--- .../bucket/signed_url.test.w_test_sim.md | 2 +- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/tools/hangar/__snapshots__/error.ts.snap b/tools/hangar/__snapshots__/error.ts.snap index 64e5e9eed79..35d9327f498 100644 --- a/tools/hangar/__snapshots__/error.ts.snap +++ b/tools/hangar/__snapshots__/error.ts.snap @@ -9,7 +9,7 @@ exports[`bool_from_json.test.w 1`] = ` | 5 | let a: bool = bool.fromJson(j.get(\\"a\\")); | ^ -at (:LINE:COL) +at /bool_from_json.test.w:5:15 Tests 1 failed (1) @@ -24,7 +24,7 @@ exports[`num_from_str.test.w 1`] = ` | // If it is run with other tests, subsequent failures will be ignored in snapshot. 3 | let a: num = num.fromStr(\\"123a\\"); | ^ -at (:LINE:COL) +at /num_from_str.test.w:3:14 Tests 1 failed (1) @@ -41,7 +41,7 @@ exports[`number_from_json.test.w 1`] = ` | 5 | let a: num = num.fromJson(j.get(\\"a\\")); | ^ -at (:LINE:COL) +at /number_from_json.test.w:5:14 Tests 1 failed (1) @@ -63,7 +63,7 @@ For more information, see https://www.winglang.io/docs/concepts/application-tree | let bucket1 = new cloud.Bucket(); 4 | let bucket2 = new cloud.Bucket(); | ^ -at (:LINE:COL) +at /repeat_construct_id.test.w:4:15 Tests 1 failed (1) @@ -85,7 +85,7 @@ For more information, see https://www.winglang.io/docs/concepts/application-tree | let bucket1 = new cloud.Bucket() as \\"{make_name()}\\"; 8 | let bucket2 = new cloud.Bucket() as \\"{make_name()}\\"; | ^ -at (:LINE:COL) +at /repeat_construct_id2.test.w:8:15 Tests 1 failed (1) @@ -102,7 +102,7 @@ exports[`string_from_json.test.w 1`] = ` | 5 | let a: str = str.fromJson(j.get(\\"a\\")); | ^ -at (:LINE:COL) +at /string_from_json.test.w:5:14 Tests 1 failed (1) @@ -119,7 +119,7 @@ exports[`struct_from_json_1.test.w 1`] = ` | 11 | Person.fromJson(j); | ^ -at (:LINE:COL) +at /struct_from_json_1.test.w:11:1 Tests 1 failed (1) @@ -137,7 +137,7 @@ exports[`struct_from_json_2.test.w 1`] = ` | 22 | Student.fromJson(missingAdvisor); | ^ -at (:LINE:COL) +at /struct_from_json_2.test.w:22:1 Tests 1 failed (1) @@ -155,7 +155,7 @@ exports[`struct_from_json_3.test.w 1`] = ` | 26 | Student.fromJson(invalidAdvisorInArray); | ^ -at (:LINE:COL) +at /struct_from_json_3.test.w:26:1 Tests 1 failed (1) @@ -172,7 +172,7 @@ exports[`struct_from_json_4.test.w 1`] = ` | 27 | Student.fromJson(invalidAdvisorInArray); | ^ -at (:LINE:COL) +at /struct_from_json_4.test.w:27:1 Tests 1 failed (1) @@ -189,7 +189,7 @@ exports[`struct_from_json_5.test.w 1`] = ` | 16 | Foo.fromJson(jFoo); | ^ -at (:LINE:COL) +at /struct_from_json_5.test.w:16:1 Tests 1 failed (1) @@ -202,7 +202,7 @@ exports[`utilities.test.w 1`] = ` --> ../../../examples/tests/error/utilities.test.w:1:1 1 | assert(false); | ^ -at (:LINE:COL) +at /utilities.test.w:1:1 Tests 1 failed (1) diff --git a/tools/hangar/__snapshots__/invalid.ts.snap b/tools/hangar/__snapshots__/invalid.ts.snap index 4b24e67dbe9..1f1a3cfe35e 100644 --- a/tools/hangar/__snapshots__/invalid.ts.snap +++ b/tools/hangar/__snapshots__/invalid.ts.snap @@ -418,7 +418,7 @@ exports[`ambiguous_api_paths.test.w 1`] = ` | api.get(\\"/path\\", handler); 12 | api.get(\\"/:variable\\", handler); | ^ -at (:LINE:COL) +at /ambiguous_api_paths.test.w:12:1 Tests 1 failed (1) @@ -2222,9 +2222,7 @@ Test Files 1 failed (1) Duration " `; -exports[`invalid compile directory 1`] = `""`; - -exports[`invalid compile directory 2`] = ` +exports[`invalid compile directory 1`] = ` "error: /external_js.js must be a sub directory of /lib --> ../../../examples/tests/invalid/lib/extern_above.w:2:3 | diff --git a/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/signed_url.test.w_test_sim.md b/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/signed_url.test.w_test_sim.md index d8c41e7db0e..7dac5c6f331 100644 --- a/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/signed_url.test.w_test_sim.md +++ b/tools/hangar/__snapshots__/test_corpus/sdk_tests/bucket/signed_url.test.w_test_sim.md @@ -10,7 +10,7 @@ It might not be implemented yet. | 8 | test "signedUrl GET (implicit)" { | ^ -at onLift (:LINE:COL) +at onLift /signed_url.test.w:8:33 Tests 1 unsupported (1) From 820297672f7f6db56d6bce167fa1f252b11a88a7 Mon Sep 17 00:00:00 2001 From: Mark McCulloh Date: Fri, 26 Jan 2024 13:21:56 -0500 Subject: [PATCH 06/17] windows doesn't have a sourceRoot --- libs/wingsdk/src/shared/bundling.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/wingsdk/src/shared/bundling.ts b/libs/wingsdk/src/shared/bundling.ts index 8ef0956a3a9..ee12b96887c 100644 --- a/libs/wingsdk/src/shared/bundling.ts +++ b/libs/wingsdk/src/shared/bundling.ts @@ -71,7 +71,10 @@ export function createBundle( const sourcemapData = JSON.parse( new TextDecoder().decode(esbuild.outputFiles[0].contents) ); - sourcemapData.sourceRoot = normalPath(sourcemapData.sourceRoot); + if (sourcemapData.sourceRoot) { + sourcemapData.sourceRoot = normalPath(sourcemapData.sourceRoot); + } + for (const [idx, source] of Object.entries( sourcemapData.sources as string[] )) { From 3d0c7166facfe430cea0f8cb6486b5a38204dfd0 Mon Sep 17 00:00:00 2001 From: Mark McCulloh Date: Fri, 26 Jan 2024 13:45:42 -0500 Subject: [PATCH 07/17] avoid string encoding cost --- libs/wingsdk/src/shared/bundling.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libs/wingsdk/src/shared/bundling.ts b/libs/wingsdk/src/shared/bundling.ts index ee12b96887c..6a6e39da2bf 100644 --- a/libs/wingsdk/src/shared/bundling.ts +++ b/libs/wingsdk/src/shared/bundling.ts @@ -52,7 +52,7 @@ export function createBundle( "@winglang/sdk": SDK_PATH, }, minify: false, - sourcemap: "external", + sourcemap: "linked", platform: "node", target: "node18", external, @@ -64,8 +64,7 @@ export function createBundle( throw new Error(`Failed to bundle function: ${errors}`); } - const output = esbuild.outputFiles[1]; - let fileContents = new TextDecoder().decode(output.contents); + const bundleOutput = esbuild.outputFiles[1]; // ensure source paths have posix path separators const sourcemapData = JSON.parse( @@ -81,13 +80,14 @@ export function createBundle( sourcemapData.sources[idx] = normalPath(source); } - fileContents += `//# sourceMappingURL=${soucemapFilename}`; - - writeFileSync(outfile, fileContents); + writeFileSync(outfile, bundleOutput.contents); writeFileSync(outfileMap, JSON.stringify(sourcemapData)); // calculate a md5 hash of the contents of asset.path - const codeHash = crypto.createHash("md5").update(fileContents).digest("hex"); + const codeHash = crypto + .createHash("md5") + .update(bundleOutput.contents) + .digest("hex"); return { entrypointPath: outfile, From 69836ff6af4da47ea038d8de6adf6880ef778ffa Mon Sep 17 00:00:00 2001 From: Mark McCulloh Date: Fri, 26 Jan 2024 14:19:49 -0500 Subject: [PATCH 08/17] add more testing --- .../tests/error/inflight_stacktraces.test.w | 23 +++++++++ examples/wing-fixture/subdir/util.w | 2 + tools/hangar/__snapshots__/error.ts.snap | 48 +++++++++++++++++++ ...ring_wing_library.test.w_compile_tf-aws.md | 5 +- tools/hangar/src/utils.ts | 2 + 5 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 examples/tests/error/inflight_stacktraces.test.w diff --git a/examples/tests/error/inflight_stacktraces.test.w b/examples/tests/error/inflight_stacktraces.test.w new file mode 100644 index 00000000000..5b94c67c925 --- /dev/null +++ b/examples/tests/error/inflight_stacktraces.test.w @@ -0,0 +1,23 @@ +bring cloud; +bring expect; + +let bucket = new cloud.Bucket(); + +test "assert" { + assert(false); +} + +test "expect.equal" { + expect.equal(1,2 ); +} + +test "bucket failed get" { + bucket.get("doesn't exist"); +} + +test "throw from closure" { + let closure = inflight () => { + throw "ouch"; + }; + closure(); +} \ No newline at end of file diff --git a/examples/wing-fixture/subdir/util.w b/examples/wing-fixture/subdir/util.w index 0b8f3a2768b..2051bffab74 100644 --- a/examples/wing-fixture/subdir/util.w +++ b/examples/wing-fixture/subdir/util.w @@ -1,4 +1,6 @@ pub class Util { + extern "../util.js" pub static inflight makeKeyInflight(name: str): str; + pub static inflight double(msg: str): str { return "{msg}{msg}"; } diff --git a/tools/hangar/__snapshots__/error.ts.snap b/tools/hangar/__snapshots__/error.ts.snap index 35d9327f498..a35508f9b63 100644 --- a/tools/hangar/__snapshots__/error.ts.snap +++ b/tools/hangar/__snapshots__/error.ts.snap @@ -17,6 +17,54 @@ Test Files 1 failed (1) Duration " `; +exports[`inflight_stacktraces.test.w 1`] = ` +"fail ┌ inflight_stacktraces.test.wsim » root/env0/test:assert + │ runtime error: assertion failed: false + │ --> ../../../examples/tests/error/inflight_stacktraces.test.w:7:3 + │ | let bucket = new cloud.Bucket(); + │ | + │ | test \\"assert\\" { + │ 7 | assert(false); + │ | ^ + └ at /inflight_stacktraces.test.w:7:3 +fail ┌ inflight_stacktraces.test.wsim » root/env1/test:expect.equal + │ runtime error: AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: + │ + │ 1 !== 2 + │ + │ --> ../../../examples/tests/error/inflight_stacktraces.test.w:11:3 + │ | } + │ | + │ | test \\"expect.equal\\" { + │ 11 | expect.equal(1,2 ); + │ | ^ + └ at /inflight_stacktraces.test.w:11:3 +fail ┌ inflight_stacktraces.test.wsim » root/env2/test:bucket failed get + │ runtime error: Object does not exist (key=doesn't exist): Error: ENOENT: no such file or directory, open '../../../examples/tests/error/target/test/inflight_stacktraces.test.wsim/.state/' + │ --> ../../../examples/tests/error/inflight_stacktraces.test.w:15:3 + │ | } + │ | + │ | test \\"bucket failed get\\" { + │ 15 | bucket.get(\\"doesn't exist\\"); + │ | ^ + └ at /inflight_stacktraces.test.w:15:3 +fail ┌ inflight_stacktraces.test.wsim » root/env3/test:throw from closure + │ runtime error: ouch + │ --> ../../../examples/tests/error/inflight_stacktraces.test.w:20:5 + │ | + │ | test \\"throw from closure\\" { + │ | let closure = inflight () => { + │ 20 | throw \\"ouch\\"; + │ | ^ + │ at closure /inflight_stacktraces.test.w:20:5 + └ at /inflight_stacktraces.test.w:22:3 + + +Tests 4 failed (4) +Test Files 1 failed (1) +Duration " +`; + exports[`num_from_str.test.w 1`] = ` "runtime error: unable to parse \\"123a\\" as a number --> ../../../examples/tests/error/num_from_str.test.w:3:14 diff --git a/tools/hangar/__snapshots__/test_corpus/valid/bring_wing_library.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/bring_wing_library.test.w_compile_tf-aws.md index a749abb2f43..a0b54a4d5aa 100644 --- a/tools/hangar/__snapshots__/test_corpus/valid/bring_wing_library.test.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/valid/bring_wing_library.test.w_compile_tf-aws.md @@ -53,6 +53,9 @@ module.exports = function({ }) { class Util { constructor({ }) { } + static async makeKeyInflight(name) { + return (require("@winglibs/testfixture/util.js")["makeKeyInflight"])(name) + } static async double(msg) { return String.raw({ raw: ["", "", ""] }, msg, msg); } @@ -293,7 +296,7 @@ class Util extends $stdlib.std.Resource { `; } _supportedOps() { - return [...super._supportedOps(), "double", "$inflight_init"]; + return [...super._supportedOps(), "makeKeyInflight", "double", "$inflight_init"]; } } module.exports = { Util }; diff --git a/tools/hangar/src/utils.ts b/tools/hangar/src/utils.ts index bd7c849c7a5..7b436dd18da 100644 --- a/tools/hangar/src/utils.ts +++ b/tools/hangar/src/utils.ts @@ -65,6 +65,8 @@ export function sanitizeOutput(output: string) { .replace(/\(\/.+:\d+:\d+\)/g, "(:LINE:COL)") // Remove absolute paths .replace(/(?<=[\s"])(\/|\w:)\S+\/(\S+)/g, "/$2") + // remove references to random state files + .replace(/\/.state\/[^ '"]+/g, "/.state/") // Remove duration from test results .replace(/Duration \d+m[\d.]+s/g, "Duration ") ); From c79ea4e6d815c02baedfa8655809df304b1873c6 Mon Sep 17 00:00:00 2001 From: "monada-bot[bot]" Date: Fri, 26 Jan 2024 19:36:55 +0000 Subject: [PATCH 09/17] chore: self mutation (e2e-2of2.diff) Signed-off-by: monada-bot[bot] --- tools/hangar/__snapshots__/error.ts.snap | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/hangar/__snapshots__/error.ts.snap b/tools/hangar/__snapshots__/error.ts.snap index a35508f9b63..64bd598ad8c 100644 --- a/tools/hangar/__snapshots__/error.ts.snap +++ b/tools/hangar/__snapshots__/error.ts.snap @@ -26,6 +26,7 @@ exports[`inflight_stacktraces.test.w 1`] = ` │ | test \\"assert\\" { │ 7 | assert(false); │ | ^ + │ at assert /helpers.ts:27:11 └ at /inflight_stacktraces.test.w:7:3 fail ┌ inflight_stacktraces.test.wsim » root/env1/test:expect.equal │ runtime error: AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: @@ -38,6 +39,7 @@ fail ┌ inflight_stacktraces.test.wsim » root/env1/test:expect.equal │ | test \\"expect.equal\\" { │ 11 | expect.equal(1,2 ); │ | ^ + │ at equal /assert.ts:25:16 └ at /inflight_stacktraces.test.w:11:3 fail ┌ inflight_stacktraces.test.wsim » root/env2/test:bucket failed get │ runtime error: Object does not exist (key=doesn't exist): Error: ENOENT: no such file or directory, open '../../../examples/tests/error/target/test/inflight_stacktraces.test.wsim/.state/' @@ -47,6 +49,7 @@ fail ┌ inflight_stacktraces.test.wsim » root/env2/test:bucket failed get │ | test \\"bucket failed get\\" { │ 15 | bucket.get(\\"doesn't exist\\"); │ | ^ + │ at activity /bucket.inflight.ts:148:17 └ at /inflight_stacktraces.test.w:15:3 fail ┌ inflight_stacktraces.test.wsim » root/env3/test:throw from closure │ runtime error: ouch From 7f667fccc1411b45cd44f1e98c80c2bf512cec58 Mon Sep 17 00:00:00 2001 From: Mark McCulloh Date: Fri, 26 Jan 2024 14:38:51 -0500 Subject: [PATCH 10/17] less precise wingsdk detection to match both lib and src --- libs/wingsdk/src/util/enhanced-error.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/wingsdk/src/util/enhanced-error.ts b/libs/wingsdk/src/util/enhanced-error.ts index b006d58c6fd..d1b4e4e040d 100644 --- a/libs/wingsdk/src/util/enhanced-error.ts +++ b/libs/wingsdk/src/util/enhanced-error.ts @@ -72,7 +72,7 @@ export async function prettyPrintError( // strip node internals .filter((item) => !item.file.startsWith("node:")) // strip wingsdk - .filter((item) => !normalPath(item.file).includes("/libs/wingsdk/src/")) + .filter((item) => !normalPath(item.file).includes("/libs/wingsdk/")) // special: remove the handler wrapper (See `cloud.Function` entrypoint for where this comes from) .filter((item) => !normalPath(item.file).match(/\.wing\/handler_\w+\.js$/)) .withSourcesAsync(); From 436720c9ab58f894617b4fed1689d135951ada21 Mon Sep 17 00:00:00 2001 From: Mark McCulloh Date: Fri, 26 Jan 2024 14:43:41 -0500 Subject: [PATCH 11/17] snap revert --- tools/hangar/__snapshots__/error.ts.snap | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/hangar/__snapshots__/error.ts.snap b/tools/hangar/__snapshots__/error.ts.snap index 64bd598ad8c..a35508f9b63 100644 --- a/tools/hangar/__snapshots__/error.ts.snap +++ b/tools/hangar/__snapshots__/error.ts.snap @@ -26,7 +26,6 @@ exports[`inflight_stacktraces.test.w 1`] = ` │ | test \\"assert\\" { │ 7 | assert(false); │ | ^ - │ at assert /helpers.ts:27:11 └ at /inflight_stacktraces.test.w:7:3 fail ┌ inflight_stacktraces.test.wsim » root/env1/test:expect.equal │ runtime error: AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: @@ -39,7 +38,6 @@ fail ┌ inflight_stacktraces.test.wsim » root/env1/test:expect.equal │ | test \\"expect.equal\\" { │ 11 | expect.equal(1,2 ); │ | ^ - │ at equal /assert.ts:25:16 └ at /inflight_stacktraces.test.w:11:3 fail ┌ inflight_stacktraces.test.wsim » root/env2/test:bucket failed get │ runtime error: Object does not exist (key=doesn't exist): Error: ENOENT: no such file or directory, open '../../../examples/tests/error/target/test/inflight_stacktraces.test.wsim/.state/' @@ -49,7 +47,6 @@ fail ┌ inflight_stacktraces.test.wsim » root/env2/test:bucket failed get │ | test \\"bucket failed get\\" { │ 15 | bucket.get(\\"doesn't exist\\"); │ | ^ - │ at activity /bucket.inflight.ts:148:17 └ at /inflight_stacktraces.test.w:15:3 fail ┌ inflight_stacktraces.test.wsim » root/env3/test:throw from closure │ runtime error: ouch From 1d2a28ea14db37f20090236e45bcd4cd7ca0f2bd Mon Sep 17 00:00:00 2001 From: Mark McCulloh Date: Fri, 26 Jan 2024 15:00:16 -0500 Subject: [PATCH 12/17] even better --- libs/wingsdk/src/util/enhanced-error.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libs/wingsdk/src/util/enhanced-error.ts b/libs/wingsdk/src/util/enhanced-error.ts index d1b4e4e040d..9c75052d3ca 100644 --- a/libs/wingsdk/src/util/enhanced-error.ts +++ b/libs/wingsdk/src/util/enhanced-error.ts @@ -72,7 +72,11 @@ export async function prettyPrintError( // strip node internals .filter((item) => !item.file.startsWith("node:")) // strip wingsdk - .filter((item) => !normalPath(item.file).includes("/libs/wingsdk/")) + .filter( + (item) => + !normalPath(item.file).includes("/libs/wingsdk/") && + !normalPath(item.file).includes("/@winglang/sdk/") + ) // special: remove the handler wrapper (See `cloud.Function` entrypoint for where this comes from) .filter((item) => !normalPath(item.file).match(/\.wing\/handler_\w+\.js$/)) .withSourcesAsync(); From 619228589cc55c101388a1ae791722952c4d7f17 Mon Sep 17 00:00:00 2001 From: Mark McCulloh Date: Fri, 26 Jan 2024 15:30:06 -0500 Subject: [PATCH 13/17] pls --- libs/wingsdk/src/util/enhanced-error.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libs/wingsdk/src/util/enhanced-error.ts b/libs/wingsdk/src/util/enhanced-error.ts index 9c75052d3ca..343fde96d0f 100644 --- a/libs/wingsdk/src/util/enhanced-error.ts +++ b/libs/wingsdk/src/util/enhanced-error.ts @@ -74,7 +74,7 @@ export async function prettyPrintError( // strip wingsdk .filter( (item) => - !normalPath(item.file).includes("/libs/wingsdk/") && + !normalPath(item.file).includes("/libs/wingsdk/src/") && !normalPath(item.file).includes("/@winglang/sdk/") ) // special: remove the handler wrapper (See `cloud.Function` entrypoint for where this comes from) @@ -83,8 +83,6 @@ export async function prettyPrintError( let traceWithSources = st.items; - // special handling: If the bottom of the stack is a js file - if (traceWithSources.length === 0) { return message; } From 7bde6c7c298cdccaddda03aa71bcadd945d5b80a Mon Sep 17 00:00:00 2001 From: "monada-bot[bot]" Date: Fri, 26 Jan 2024 20:48:23 +0000 Subject: [PATCH 14/17] chore: self mutation (build.diff) Signed-off-by: monada-bot[bot] --- libs/wingsdk/test/target-sim/__snapshots__/topic.test.ts.snap | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/wingsdk/test/target-sim/__snapshots__/topic.test.ts.snap b/libs/wingsdk/test/target-sim/__snapshots__/topic.test.ts.snap index 9f66179424b..415ef2b8099 100644 --- a/libs/wingsdk/test/target-sim/__snapshots__/topic.test.ts.snap +++ b/libs/wingsdk/test/target-sim/__snapshots__/topic.test.ts.snap @@ -157,7 +157,6 @@ exports[`topic publishes messages to multiple subscribers 1`] = ` "Publish (message=Alpha).", "Sending message (message=Alpha, subscriber=sim-0).", "InvokeAsync (payload=\\"Alpha\\").", - "Received Alpha", "Sending message (message=Alpha, subscriber=sim-3).", "InvokeAsync (payload=\\"Alpha\\").", "@winglang/sdk.sim.EventMapping deleted.", From b27dcdc2f0bc28322a77c4d543cb099a6dd3bee7 Mon Sep 17 00:00:00 2001 From: Mark McCulloh Date: Fri, 26 Jan 2024 15:50:23 -0500 Subject: [PATCH 15/17] undo snap change, cmon --- libs/wingsdk/test/target-sim/__snapshots__/topic.test.ts.snap | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/wingsdk/test/target-sim/__snapshots__/topic.test.ts.snap b/libs/wingsdk/test/target-sim/__snapshots__/topic.test.ts.snap index 415ef2b8099..9f66179424b 100644 --- a/libs/wingsdk/test/target-sim/__snapshots__/topic.test.ts.snap +++ b/libs/wingsdk/test/target-sim/__snapshots__/topic.test.ts.snap @@ -157,6 +157,7 @@ exports[`topic publishes messages to multiple subscribers 1`] = ` "Publish (message=Alpha).", "Sending message (message=Alpha, subscriber=sim-0).", "InvokeAsync (payload=\\"Alpha\\").", + "Received Alpha", "Sending message (message=Alpha, subscriber=sim-3).", "InvokeAsync (payload=\\"Alpha\\").", "@winglang/sdk.sim.EventMapping deleted.", From e4799725db2c1966dbbdfe09cecf0bae7da1b40e Mon Sep 17 00:00:00 2001 From: "monada-bot[bot]" Date: Fri, 26 Jan 2024 21:08:31 +0000 Subject: [PATCH 16/17] chore: self mutation (build.diff) Signed-off-by: monada-bot[bot] --- libs/wingsdk/test/target-sim/__snapshots__/topic.test.ts.snap | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/wingsdk/test/target-sim/__snapshots__/topic.test.ts.snap b/libs/wingsdk/test/target-sim/__snapshots__/topic.test.ts.snap index 9f66179424b..415ef2b8099 100644 --- a/libs/wingsdk/test/target-sim/__snapshots__/topic.test.ts.snap +++ b/libs/wingsdk/test/target-sim/__snapshots__/topic.test.ts.snap @@ -157,7 +157,6 @@ exports[`topic publishes messages to multiple subscribers 1`] = ` "Publish (message=Alpha).", "Sending message (message=Alpha, subscriber=sim-0).", "InvokeAsync (payload=\\"Alpha\\").", - "Received Alpha", "Sending message (message=Alpha, subscriber=sim-3).", "InvokeAsync (payload=\\"Alpha\\").", "@winglang/sdk.sim.EventMapping deleted.", From d3c4f4e04ae20f86f176b218d8d5fb054cb3d105 Mon Sep 17 00:00:00 2001 From: Mark McCulloh Date: Fri, 26 Jan 2024 16:33:37 -0500 Subject: [PATCH 17/17] we really don't need snapshots for this --- .../__snapshots__/topic.test.ts.snap | 39 ------------------- libs/wingsdk/test/target-sim/topic.test.ts | 12 +++++- 2 files changed, 10 insertions(+), 41 deletions(-) diff --git a/libs/wingsdk/test/target-sim/__snapshots__/topic.test.ts.snap b/libs/wingsdk/test/target-sim/__snapshots__/topic.test.ts.snap index 415ef2b8099..a8da47fa3bd 100644 --- a/libs/wingsdk/test/target-sim/__snapshots__/topic.test.ts.snap +++ b/libs/wingsdk/test/target-sim/__snapshots__/topic.test.ts.snap @@ -127,42 +127,3 @@ exports[`create a topic 1`] = ` }, } `; - -exports[`topic publishes messages as they are received 1`] = ` -[ - "@winglang/sdk.cloud.Function created.", - "@winglang/sdk.cloud.Topic created.", - "@winglang/sdk.sim.EventMapping created.", - "Publish (message=Alpha).", - "Sending message (message=Alpha, subscriber=sim-0).", - "InvokeAsync (payload=\\"Alpha\\").", - "Received Alpha", - "Publish (message=Beta).", - "Sending message (message=Beta, subscriber=sim-0).", - "InvokeAsync (payload=\\"Beta\\").", - "Received Beta", - "@winglang/sdk.sim.EventMapping deleted.", - "@winglang/sdk.cloud.Topic deleted.", - "@winglang/sdk.cloud.Function deleted.", -] -`; - -exports[`topic publishes messages to multiple subscribers 1`] = ` -[ - "@winglang/sdk.cloud.Function created.", - "@winglang/sdk.cloud.Topic created.", - "@winglang/sdk.sim.EventMapping created.", - "@winglang/sdk.cloud.Function created.", - "@winglang/sdk.sim.EventMapping created.", - "Publish (message=Alpha).", - "Sending message (message=Alpha, subscriber=sim-0).", - "InvokeAsync (payload=\\"Alpha\\").", - "Sending message (message=Alpha, subscriber=sim-3).", - "InvokeAsync (payload=\\"Alpha\\").", - "@winglang/sdk.sim.EventMapping deleted.", - "@winglang/sdk.cloud.Function deleted.", - "@winglang/sdk.sim.EventMapping deleted.", - "@winglang/sdk.cloud.Topic deleted.", - "@winglang/sdk.cloud.Function deleted.", -] -`; diff --git a/libs/wingsdk/test/target-sim/topic.test.ts b/libs/wingsdk/test/target-sim/topic.test.ts index 8111d272043..d8c364657e4 100644 --- a/libs/wingsdk/test/target-sim/topic.test.ts +++ b/libs/wingsdk/test/target-sim/topic.test.ts @@ -55,7 +55,10 @@ test("topic publishes messages as they are received", async () => { // THEN await s.stop(); - expect(listMessages(s)).toMatchSnapshot(); + const messages = listMessages(s); + const alphaIndex = messages.findIndex((m) => m.startsWith("Received Alpha")); + const betaIndex = messages.findIndex((m) => m.startsWith("Received Beta")); + expect(alphaIndex).toBeLessThan(betaIndex); }); test("topic publishes messages to multiple subscribers", async () => { @@ -78,8 +81,13 @@ test("topic publishes messages to multiple subscribers", async () => { await topicClient.publish("Alpha"); // THEN + await waitUntilTrace(s, (trace) => + trace.data.message.startsWith("Received Alpha") + ); + await waitUntilTrace(s, (trace) => + trace.data.message.startsWith("Also received Alpha") + ); await s.stop(); - expect(listMessages(s)).toMatchSnapshot(); }); test("topic has no display hidden property", async () => {