Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkMcCulloh committed Apr 5, 2024
1 parent 1bfc047 commit c8a85ef
Show file tree
Hide file tree
Showing 14 changed files with 149 additions and 99 deletions.
2 changes: 1 addition & 1 deletion examples/tests/invalid/extern_static.test.w
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class Foo {
extern "../valid/external_js.js" inflight getGreeting(name: str): str;
extern "../valid/external_ts.ts" inflight getGreeting(name: str): str;
//^ Error: extern methods must be declared "static"
}
2 changes: 1 addition & 1 deletion examples/tests/invalid/lib/extern_above.w
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class Foo1 {
extern "../../valid/external_js.js" static getGreeting(name: str): str;
extern "../../valid/external_ts.ts" static getGreeting(name: str): str;
//^ must be a sub directory of the entrypoint
}
14 changes: 7 additions & 7 deletions examples/tests/valid/extern_implementation.test.w
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
bring cloud;

class Foo {
extern "./external_js.js" pub static getGreeting(name: str): str;
extern "./external_js.js" static inflight regexInflight(pattern: str, text: str): bool;
extern "./external_js.js" static inflight getUuid(): str;
extern "./external_js.js" static inflight getData(): str;
extern "./external_js.js" pub static inflight print(msg: str): void;
extern "./external_js.js" pub static preflightBucket(bucket: cloud.Bucket, id: str): Json;
extern "./external_ts.ts" pub static getGreeting(name: str): str;
extern "./external_ts.ts" static inflight regexInflight(pattern: str, text: str): bool;
extern "./external_ts.ts" static inflight getUuid(): str;
extern "./external_ts.ts" static inflight getData(): str;
extern "./external_ts.ts" pub static inflight print(msg: str): void;
extern "./external_ts.ts" pub static preflightBucket(bucket: cloud.Bucket, id: str): void;

pub inflight call() {
assert(Foo.regexInflight("[a-z]+-\\d+", "abc-123"));
Expand All @@ -22,7 +22,7 @@ assert(Foo.getGreeting("Wingding") == "Hello, Wingding!");
let f = new Foo();

let bucket = new cloud.Bucket() as "my-bucket";
let result = Foo.preflightBucket(bucket, "my-bucket");
Foo.preflightBucket(bucket, "my-bucket");

test "call" {
f.call();
Expand Down
25 changes: 0 additions & 25 deletions examples/tests/valid/external_js.js

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export default interface extern {
getData: () => Promise<string>,
getGreeting: (name: string) => string,
getUuid: () => Promise<string>,
preflightBucket: (bucket: Bucket, id: string) => Readonly<any>,
preflightBucket: (bucket: Bucket, id: string) => void,
print: (msg: string) => Promise<void>,
regexInflight: (pattern: string, text: string) => Promise<boolean>,
}
Expand Down
31 changes: 31 additions & 0 deletions examples/tests/valid/external_ts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import assert from "assert";
import extern from "./external_ts.extern";

export const getGreeting: extern["getGreeting"] = function (name) {
return `Hello, ${name}!`;
};

export const regexInflight: extern["regexInflight"] = async function (
pattern,
text
) {
const regex = new RegExp(pattern);
return regex.test(text);
};

export const getUuid: extern["getUuid"] = async function () {
let uuid = require("uuid");
return uuid.v4();
};

export const getData: extern["getData"] = async function () {
return require("./exported_data.js");
};

export const print: extern["print"] = async function (msg) {
console.log(`printing ${msg}`);
};

export const preflightBucket: extern["preflightBucket"] = (bucket, id) => {
assert.strictEqual(bucket.node.id, id);
};
3 changes: 0 additions & 3 deletions libs/wingcompiler/.npmignore

This file was deleted.

6 changes: 0 additions & 6 deletions libs/wingcompiler/jest.config.js

This file was deleted.

4 changes: 3 additions & 1 deletion libs/wingcompiler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"description": "Wing Compiler",
"files": [
"wingc.wasm",
"preflight.shim.js",
"dist/"
],
"license": "MIT",
Expand All @@ -23,8 +24,9 @@
"package": "bump-pack -b"
},
"dependencies": {
"@winglang/sdk": "workspace:^",
"@wingcloud/framework": "workspace:^",
"@winglang/sdk": "workspace:^",
"jiti": "^1.21.0",
"wasi-js": "^1.7.3"
},
"bundledDependencies": [
Expand Down
58 changes: 58 additions & 0 deletions libs/wingcompiler/preflight.shim.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/// This serves as the preflight execution entrypoint to set up the following behaviors
/// 1. Register jiti to handle transforms in loaded modules whenever necessary
/// 2. Override module resolution to force @winglang/sdk to always resolve to the same path
/// 3. Handle communication with parent process to handle errors and load the true entrypoint
///
/// This file has the following expectations:
/// 1. The environment variable WING_JITI_ENTRYPOINT is a JSON string of the entrypoint to load
/// 2. Runs in a child process with an IPC channel to the parent process

process.setUncaughtExceptionCaptureCallback((reason) => {
if (reason instanceof Error) {
// The Error object does not serialize well over IPC (even with 'advanced' serialization)
// So we extract the properties we need to recreate most error objects
reason = {
message: reason.message,
stack: reason.stack,
name: reason.name,
code: reason.code,
};
}
process.send(reason);
});

if (!process.send) {
throw new Error(
"process.send is undefined. This file should only be run in a child process with an IPC connection to the parent."
);
}

var Module = require("module");
const { join } = require("path");
const original_resolveFilename = Module._resolveFilename;
const WINGSDK = "@winglang/sdk";
const WINGSDK_PATH = require.resolve(WINGSDK);
const WINGSDK_DIR = join(WINGSDK_PATH, "..", "..");

Module._resolveFilename = function () {
const path = arguments[0];
if (path === WINGSDK) return WINGSDK_PATH;
if (path.startsWith(WINGSDK)) {
arguments[0] = path.replace(WINGSDK, WINGSDK_DIR);
}
return original_resolveFilename.apply(this, arguments);
};

if (!process.env.WING_JITI_ENTRYPOINT) {
throw new Error("Missing environment variable WING_JITI_ENTRYPOINT");
}
const entrypoint = JSON.parse(process.env.WING_JITI_ENTRYPOINT);
delete process.env.WING_JITI_ENTRYPOINT;

const jiti = require("jiti")(__filename, {
sourceMaps: true,
interopDefault: true,
});
jiti(entrypoint);

process.send(null);
62 changes: 26 additions & 36 deletions libs/wingcompiler/src/compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import { normalPath } from "./util";
import { existsSync } from "fs";
import { BuiltinPlatform } from "./constants";
import { CompileError, PreflightError } from "./errors";
import { Worker } from "worker_threads";
import { readFile } from "fs/promises";
import { fork } from "child_process";

// increase the stack trace limit to 50, useful for debugging Rust panics
// (not setting the limit too high in case of infinite recursion)
Expand Down Expand Up @@ -184,7 +184,8 @@ export async function compile(entrypoint: string, options: CompileOptions): Prom
WING_VALUES: options.value?.length == 0 ? undefined : options.value,
WING_VALUES_FILE: options.values ?? defaultValuesFile(),
WING_NODE_MODULES: wingNodeModules,
WING_IMPORTED_NAMESPACES: compileForPreflightResult.compilerOutput?.imported_namespaces.join(";"),
WING_IMPORTED_NAMESPACES:
compileForPreflightResult.compilerOutput?.imported_namespaces.join(";"),
};

if (options.rootId) {
Expand All @@ -201,7 +202,10 @@ export async function compile(entrypoint: string, options: CompileOptions): Prom
delete preflightEnv.Path;
}
}
await runPreflightCodeInWorkerThread(compileForPreflightResult.preflightEntrypoint, preflightEnv);
await runPreflightCodeInWorkerThread(
compileForPreflightResult.preflightEntrypoint,
preflightEnv
);
}
return synthDir;
}
Expand All @@ -221,7 +225,7 @@ interface CompileForPreflightResult {
readonly preflightEntrypoint: string;
readonly compilerOutput?: {
imported_namespaces: string[];
}
};
}

async function compileForPreflight(props: {
Expand All @@ -248,8 +252,8 @@ npm i @wingcloud/framework
preflightEntrypoint: await typescriptFramework.compile({
workDir: props.workDir,
entrypoint: props.entrypointFile,
})
}
}),
};
} else {
let env: Record<string, string> = {
RUST_BACKTRACE: "full",
Expand Down Expand Up @@ -301,22 +305,20 @@ npm i @wingcloud/framework

return {
preflightEntrypoint: join(props.workDir, WINGC_PREFLIGHT),
compilerOutput: JSON.parse(
compilerOutput as string
),
}
compilerOutput: JSON.parse(compilerOutput as string),
};
}
}

/**
* Check if in the current working directory there is a default values file
* only the first match is returned from the list of default values files
*
* only the first match is returned from the list of default values files
*
* @returns default values file from the current working directory
*/
function defaultValuesFile() {
const defaultConfigs = [ "wing.toml", "wing.yaml", "wing.yml", "wing.json"]
const defaultConfigs = ["wing.toml", "wing.yaml", "wing.yml", "wing.json"];

for (const configFile of defaultConfigs) {
if (existsSync(join(process.cwd(), configFile))) {
return configFile;
Expand All @@ -330,31 +332,19 @@ async function runPreflightCodeInWorkerThread(
env: Record<string, string | undefined>
): Promise<void> {
try {
// Create a shimmed entrypoint that ensures we always load the compiler's version of the SDK
const sdkEntrypoint = require.resolve("@winglang/sdk");
const shim = `\
var Module = require('module');
var original_resolveFilename = Module._resolveFilename;
var WINGSDK = '@winglang/sdk';
var WINGSDK_PATH = '${normalPath(sdkEntrypoint)}';
var WINGSDK_DIR = '${normalPath(join(sdkEntrypoint, "..", ".."))}';
Module._resolveFilename = function () {
const path = arguments[0];
if(path === WINGSDK) return WINGSDK_PATH;
if(path.startsWith(WINGSDK)){
arguments[0] = path.replace(WINGSDK, WINGSDK_DIR);
}
return original_resolveFilename.apply(this, arguments);
};
require('${normalPath(entrypoint)}');
`;
env.WING_JITI_ENTRYPOINT = JSON.stringify(entrypoint);

await new Promise((resolve, reject) => {
const worker = new Worker(shim, {
const worker = fork(join(__dirname, "..", "preflight.shim.js"), {
env,
eval: true,
stdio: "inherit",
});
worker.on("message", (message: any) => {
if (message === null) {
resolve(undefined);
} else {
reject(message);
}
});
worker.on("error", reject);
worker.on("exit", (code) => {
Expand Down
17 changes: 10 additions & 7 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit c8a85ef

Please sign in to comment.