From a17819b08cb937aa336f744d741566ab4a96e208 Mon Sep 17 00:00:00 2001 From: Mehul Kar Date: Mon, 15 May 2023 16:04:07 -0700 Subject: [PATCH] fix: set repoRoot on http cache so cache can be restored (#4956) repoRoot was never passed in before, but in 829e5ac2be31accee0f2bd1c3048ac092e37d01c, changing the implementation of `restoreTar` caused the handling of an empty string for this argument to change. Before, the contents of the tar would get anchored before attempting to write to disk, but in cacheItem, this affordance does not seem to exist. We could add it back, but the implementation looks different enough that it is easier to just pass in the repoRoot. Additionally, there may be other issues with running turbo from subdirectories, since the inferred path from an empty string may be defaulting to cwd, which would be the incorrect place to restore from a remote cache. --- cli/internal/cache/cache.go | 2 +- cli/internal/cache/cache_http.go | 3 +- .../js/src/transforms/webpack-loaders.ts | 113 ++++++++++++++++-- crates/turbopack/src/module_options/mod.rs | 12 +- crates/turbopack/src/resolve.rs | 3 +- 5 files changed, 117 insertions(+), 16 deletions(-) diff --git a/cli/internal/cache/cache.go b/cli/internal/cache/cache.go index 8b74272ed10dd..e5e24c1a9d133 100644 --- a/cli/internal/cache/cache.go +++ b/cli/internal/cache/cache.go @@ -129,7 +129,7 @@ func newSyncCache(opts Opts, repoRoot turbopath.AbsoluteSystemPath, client clien } if useHTTPCache { - implementation := newHTTPCache(opts, client, recorder) + implementation := newHTTPCache(opts, client, recorder, repoRoot) cacheImplementations = append(cacheImplementations, implementation) } diff --git a/cli/internal/cache/cache_http.go b/cli/internal/cache/cache_http.go index 0e8d1ce5437b2..f335a954949bc 100644 --- a/cli/internal/cache/cache_http.go +++ b/cli/internal/cache/cache_http.go @@ -267,12 +267,13 @@ func (cache *httpCache) CleanAll() { func (cache *httpCache) Shutdown() {} -func newHTTPCache(opts Opts, client client, recorder analytics.Recorder) *httpCache { +func newHTTPCache(opts Opts, client client, recorder analytics.Recorder, repoRoot turbopath.AbsoluteSystemPath) *httpCache { return &httpCache{ writable: true, client: client, requestLimiter: make(limiter, 20), recorder: recorder, + repoRoot: repoRoot, signerVerifier: &ArtifactSignatureAuthentication{ // TODO(Gaspar): this should use RemoteCacheOptions.TeamId once we start // enforcing team restrictions for repositories. diff --git a/crates/turbopack-node/js/src/transforms/webpack-loaders.ts b/crates/turbopack-node/js/src/transforms/webpack-loaders.ts index 742496b4b071f..8a9d1d2f6f913 100644 --- a/crates/turbopack-node/js/src/transforms/webpack-loaders.ts +++ b/crates/turbopack-node/js/src/transforms/webpack-loaders.ts @@ -18,9 +18,9 @@ import { type LoaderConfig = | string | { - loader: string; - options: { [k: string]: unknown }; - }; + loader: string; + options: { [k: string]: unknown }; + }; // @ts-ignore let runLoaders: typeof import("loader-runner"); @@ -41,6 +41,66 @@ const toPath = (file: string) => { return sep !== "/" ? relPath.replaceAll(sep, "/") : relPath; }; +const LogType = Object.freeze({ + error: /** @type {"error"} */ ("error"), // message, c style arguments + warn: /** @type {"warn"} */ ("warn"), // message, c style arguments + info: /** @type {"info"} */ ("info"), // message, c style arguments + log: /** @type {"log"} */ ("log"), // message, c style arguments + debug: /** @type {"debug"} */ ("debug"), // message, c style arguments + + trace: /** @type {"trace"} */ ("trace"), // no arguments + + group: /** @type {"group"} */ ("group"), // [label] + groupCollapsed: /** @type {"groupCollapsed"} */ ("groupCollapsed"), // [label] + groupEnd: /** @type {"groupEnd"} */ ("groupEnd"), // [label] + + profile: /** @type {"profile"} */ ("profile"), // [profileName] + profileEnd: /** @type {"profileEnd"} */ ("profileEnd"), // [profileName] + + time: /** @type {"time"} */ ("time"), // name, time as [seconds, nanoseconds] + + clear: /** @type {"clear"} */ ("clear"), // no arguments + status: /** @type {"status"} */ ("status") // message, arguments +}); + +const loaderFlag = "LOADER_EXECUTION"; + +const cutOffByFlag = (stack, flag) => { + const errorStack = stack.split("\n"); + for (let i = 0; i < errorStack.length; i++) { + if (errorStack[i].includes(flag)) { + errorStack.length = i; + } + } + return errorStack.join("\n"); +}; + +/** + * @param {string} stack stack trace + * @returns {string} stack trace without the loader execution flag included + */ +const cutOffLoaderExecution = stack => cutOffByFlag(stack, loaderFlag); + +class DummySpan { + traceChild() { + return new DummySpan(); + } + + traceFn(fn: (span: DummySpan) => T): T { + try { + return fn(this) + } finally { + } + } + + async traceAsyncFn(fn: (span: DummySpan) => T | Promise): Promise { + try { + return await fn(this) + } finally { + } + } +} + const transform = ( ipc: Ipc, content: string, @@ -59,6 +119,15 @@ const transform = ( { resource, context: { + currentTraceSpan: new DummySpan(), + /*utils: { + contextify: (context, request) => { + return request + .split("!") + .map(r => absoluteToRequest(context, r)).join(""); + //.join("!");; + } + },*/ rootContext: contextDir, getOptions() { const entry = this.loaders[this.loaderIndex]; @@ -66,9 +135,31 @@ const transform = ( ? entry.options : {}; }, + getResolve: () => ({}), emitWarning: makeErrorEmitter("warning", ipc), emitError: makeErrorEmitter("error", ipc), + getLogger: (name) => (type, args) => { + let trace; + switch (type) { + case LogType.warn: + case LogType.error: + case LogType.trace: + trace = cutOffLoaderExecution(new Error("Trace").stack) + .split("\n") + .slice(3); + break; + } + const logEntry = { + time: Date.now(), + type, + args, + trace + } + + this.hooks.log.call(name, logEntry) + }, }, + loaders: loadersWithOptions.map((loader) => ({ loader: __turbopack_external_require__.resolve(loader.loader, { paths: [resourceDir], @@ -113,15 +204,15 @@ function makeErrorEmitter(severity: "warning" | "error", ipc: Ipc) { error: error instanceof Error ? { - name: error.name, - message: error.message, - stack: parseStackTrace(error.stack), - } + name: error.name, + message: error.message, + stack: parseStackTrace(error.stack), + } : { - name: "Error", - message: error, - stack: [], - }, + name: "Error", + message: error, + stack: [], + }, }); }; } diff --git a/crates/turbopack/src/module_options/mod.rs b/crates/turbopack/src/module_options/mod.rs index f85db4645c18d..09e495e7ecbf2 100644 --- a/crates/turbopack/src/module_options/mod.rs +++ b/crates/turbopack/src/module_options/mod.rs @@ -465,10 +465,20 @@ impl ModuleOptionsVc { ModuleRuleCondition::not(ModuleRuleCondition::ResourceIsVirtualAsset), ]), vec![ + // [TODO]: should accept rules as an option + if ext == ".scss" || ext == ".sass" { + ModuleRuleEffect::ModuleType(ModuleType::CssModule(css_transforms)) + } else { + ModuleRuleEffect::ModuleType(ModuleType::Ecmascript { + transforms: app_transforms, + options: ecmascript_options.clone(), + }) + }, + /* ModuleRuleEffect::ModuleType(ModuleType::Ecmascript { transforms: app_transforms, options: ecmascript_options.clone(), - }), + }), */ ModuleRuleEffect::SourceTransforms(SourceTransformsVc::cell(vec![ WebpackLoadersVc::new( node_evaluate_asset_context( diff --git a/crates/turbopack/src/resolve.rs b/crates/turbopack/src/resolve.rs index 4d885b9957c13..0785815909614 100644 --- a/crates/turbopack/src/resolve.rs +++ b/crates/turbopack/src/resolve.rs @@ -112,8 +112,7 @@ async fn base_resolve_options( } let import_map = import_map.cell(); - let mut plugins = opt.plugins.clone(); - plugins.push(UnsupportedSassResolvePluginVc::new(root).as_resolve_plugin()); + let plugins = opt.plugins.clone(); Ok(ResolveOptions { extensions: if let Some(environment) = emulating {