Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correct paths windows backslashes and spawn shell param. #112

Merged
merged 3 commits into from
Jan 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
${{ runner.os }}-

- name: Setup PureScript dependencies
run: npm i --global purescript@0.15.10 purs-tidy@latest spago@latest purescript-psa@latest esbuild@latest
run: npm i --global purescript@0.15.15 purs-tidy@latest spago@latest purescript-psa@latest esbuild@latest

- name: Cache PureScript dependencies
uses: actions/cache@v2
Expand Down
58 changes: 33 additions & 25 deletions backend-es/src/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ import Data.Map as Map
import Data.Maybe (Maybe(..), fromMaybe, maybe)
import Data.Monoid (guard, power)
import Data.Newtype (over2, unwrap)
import Data.Nullable (toMaybe)
import Data.Number.Format as Number
import Data.Ord.Down (Down(..))
import Data.Posix.Signal (Signal(..))
import Data.Set (Set)
import Data.Set as Set
import Data.String (Pattern(..))
import Data.String (Pattern(..), Replacement(..))
import Data.String as String
import Data.String.CodeUnits as SCU
import Data.Traversable (traverse)
Expand All @@ -36,9 +37,9 @@ import Effect.Class.Console as Console
import Effect.Now (now)
import Effect.Ref (Ref)
import Effect.Ref as Ref
import Node.ChildProcess (Exit(..), StdIOBehaviour(..), defaultSpawnOptions)
import Node.ChildProcess as ChildProcess
import Node.ChildProcess.Types (Exit(..), enableShell, pipe, shareStream)
import Node.Encoding (Encoding(..))
import Node.EventEmitter (on_)
import Node.FS.Aff (writeTextFile)
import Node.FS.Aff as FS
import Node.FS.Perms as Perms
Expand All @@ -47,7 +48,10 @@ import Node.FS.Stream (createReadStream, createWriteStream)
import Node.Path (FilePath)
import Node.Path as Path
import Node.Process as Process
import Node.Stream (errorH, finishH)
import Node.Stream as Stream
import Node.UnsafeChildProcess.Safe (exitH, killSignal)
import Node.UnsafeChildProcess.Unsafe as UnsafeChildProcess
import PureScript.Backend.Optimizer.Codegen.EcmaScript (codegenModule, esModulePath)
import PureScript.Backend.Optimizer.Codegen.EcmaScript.Builder (basicBuildMain, externalDirectivesFromFile)
import PureScript.Backend.Optimizer.Codegen.EcmaScript.Foreign (esForeignSemantics)
Expand All @@ -59,7 +63,6 @@ import PureScript.CST.Lexer (lexToken)
import PureScript.CST.Lexer as Lexer
import PureScript.CST.Types (Token(..))
import PureScript.CST.Types as CST
import Unsafe.Coerce (unsafeCoerce)
import Version as Version

type BuildArgs =
Expand Down Expand Up @@ -223,7 +226,7 @@ type BuildState =
}

main :: FilePath -> Effect Unit
main cliRoot =
main cliRoot = do
parseArgs >>= case _ of
Left err ->
Console.error $ ArgParser.printArgError err
Expand Down Expand Up @@ -341,8 +344,11 @@ main cliRoot =
, "--outfile=" <> bundleArgs.targetFile
, "--bundle"
]
if shouldInvokeMain then do
spawnFromParentWithStdin "esbuild" esBuildArgs $ Just $ "import { main } from '" <> entryPath <> "'; main();"
fixBackSlash = String.replaceAll (Pattern "\\") (Replacement "\\\\")
if shouldInvokeMain then
spawnFromParentWithStdin "esbuild" esBuildArgs
$ Just
$ "import { main } from '" <> fixBackSlash entryPath <> "'; main();"
else
spawnFromParentWithStdin "esbuild" (Array.snoc esBuildArgs entryPath) Nothing

Expand All @@ -354,19 +360,17 @@ copyFile from to = do
makeAff \k -> do
src <- createReadStream from
dst <- createWriteStream to
res <- Stream.pipe src dst
Stream.onError src (k <<< Left)
Stream.onError dst (k <<< Left)
Stream.onError res (k <<< Left)
Stream.onFinish res (k (Right unit))
Stream.pipe src dst
src # on_ errorH (k <<< Left)
dst # on_ errorH (k <<< Left)
dst # on_ finishH (k (Right unit))
pure $ effectCanceler do
Stream.destroy res
Stream.destroy dst
Stream.destroy src

writeString :: forall r. Stream.Writable r -> String -> Aff Unit
writeString stream str = makeAff \k -> do
_ <- Stream.writeString stream UTF8 str (k <<< maybe (Right unit) Left)
_ <- Stream.writeString' stream UTF8 str (k <<< maybe (Right unit) Left)
pure nonCanceler

mkdirp :: FilePath -> Aff Unit
Expand All @@ -377,24 +381,28 @@ esModulePackageJson = """{"type": "module"}"""

spawnFromParentWithStdin :: String -> Array String -> Maybe String -> Aff Unit
spawnFromParentWithStdin command args input = makeAff \k -> do
childProc <- ChildProcess.spawn command args defaultSpawnOptions
{ stdio =
[ Just $ Pipe
, Just $ ShareStream (unsafeCoerce Process.stdout)
, Just $ ShareStream (unsafeCoerce Process.stderr)
-- To preserve colors in stdout need to pass it into spawn's stdio.
childProc <- UnsafeChildProcess.spawn' command args
{ stdio:
[ pipe
, shareStream Process.stdout
, shareStream Process.stderr
]
, shell: enableShell
}

for_ input \inp -> do
_ <- Stream.writeString (ChildProcess.stdin childProc) UTF8 inp mempty
Stream.end (ChildProcess.stdin childProc) mempty
ChildProcess.onExit childProc case _ of
for_ (toMaybe $ UnsafeChildProcess.unsafeStdin childProc) \stdin -> do
_ <- Stream.writeString stdin UTF8 inp
Stream.end stdin
childProc # on_ exitH case _ of
Normally code
| code > 0 -> Process.exit code
| code > 0 -> Process.exit' code
| otherwise -> k (Right unit)
BySignal _ ->
Process.exit 1
Process.exit' 1
pure $ effectCanceler do
ChildProcess.kill SIGABRT childProc
void $ killSignal SIGABRT childProc

timeDiff :: Instant -> Instant -> Milliseconds
timeDiff = over2 Milliseconds (flip (-)) `on` Instant.unInstant
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ basicBuildMain options = do
Left errors -> do
for_ errors \(Tuple filePath err) -> do
Console.error $ filePath <> " " <> err
liftEffect $ Process.exit 1
liftEffect $ Process.exit' 1
Right coreFnModules -> do
options.onCodegenBefore
coreFnModules # buildModules
Expand Down
4 changes: 2 additions & 2 deletions backend-es/test/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ runSnapshotTests { accept, filter, traceIdents } = do
Left errors -> do
for_ errors \(Tuple filePath err) -> do
Console.error $ filePath <> " " <> err
liftEffect $ Process.exit 1
liftEffect $ Process.exit' 1
Right coreFnModules -> do
let { directives } = parseDirectiveFile defaultDirectives
copyFile (Path.concat [ "..", "..", "runtime.js" ]) (Path.concat [ testOut, "runtime.js" ])
Expand Down Expand Up @@ -185,7 +185,7 @@ runSnapshotTests { accept, filter, traceIdents } = do
Console.log diff
pure false
unless (Foldable.and results) do
liftEffect $ Process.exit 1
liftEffect $ Process.exit' 1

hasFails :: BackendModule -> Maybe String
hasFails = findMap go <<< _.comments
Expand Down
32 changes: 17 additions & 15 deletions backend-es/test/Utils.purs
Original file line number Diff line number Diff line change
Expand Up @@ -10,36 +10,39 @@ import Effect.Aff (Aff, Error, effectCanceler, error, makeAff, throwError)
import Effect.Class (liftEffect)
import Node.Buffer (Buffer, freeze)
import Node.Buffer.Immutable as ImmutableBuffer
import Node.ChildProcess (ChildProcess, ExecResult, Exit(..), defaultExecOptions)
import Node.ChildProcess (ChildProcess, ExecResult, exitH)
import Node.ChildProcess as ChildProcess
import Node.ChildProcess.Types (Exit(..))
import Node.Encoding (Encoding(..))
import Node.EventEmitter (on_)
import Node.FS.Aff as FS
import Node.FS.Perms (mkPerms)
import Node.FS.Perms as Perms
import Node.FS.Stats as Stats
import Node.FS.Stream (createReadStream, createWriteStream)
import Node.Path (FilePath)
import Node.Process as Process
import Node.Stream (errorH, finishH)
import Node.Stream as Stream

spawnFromParent :: String -> Array String -> Aff Unit
spawnFromParent command args = makeAff \k -> do
childProc <- spawnImpl command args
ChildProcess.onExit childProc case _ of
childProc # on_ exitH case _ of
Normally code
| code > 0 -> Process.exit code
| code > 0 -> Process.exit' code
| otherwise -> k (Right unit)
BySignal _ ->
Process.exit 1
Process.exit' 1
pure $ effectCanceler do
ChildProcess.kill SIGABRT childProc
void $ ChildProcess.killSignal SIGABRT childProc

execWithStdin :: String -> String -> Aff ExecResult
execWithStdin command input = makeAff \k -> do
childProc <- ChildProcess.exec command defaultExecOptions (k <<< pure)
_ <- Stream.writeString (ChildProcess.stdin childProc) UTF8 input mempty
Stream.end (ChildProcess.stdin childProc) mempty
pure $ effectCanceler $ ChildProcess.kill SIGABRT childProc
childProc <- ChildProcess.exec' command identity (k <<< pure)
_ <- Stream.writeString' (ChildProcess.stdin childProc) UTF8 input mempty
(ChildProcess.stdin childProc) # on_ finishH mempty
pure $ effectCanceler $ void $ ChildProcess.killSignal SIGABRT childProc

bufferToUTF8 :: Buffer -> Aff String
bufferToUTF8 = liftEffect <<< map (ImmutableBuffer.toString UTF8) <<< freeze
Expand All @@ -62,15 +65,14 @@ copyFile from to = do
stats <- FS.stat from
unless (Stats.isFile stats) do
throwError $ error $ "Not a file: " <> from
--FS.copyFile from to
makeAff \k -> do
src <- createReadStream from
dst <- createWriteStream to
res <- Stream.pipe src dst
Stream.onError src (k <<< Left)
Stream.onError dst (k <<< Left)
Stream.onError res (k <<< Left)
Stream.onFinish res (k (Right unit))
Stream.pipe src dst
src # on_ errorH (k <<< Left)
dst # on_ errorH (k <<< Left)
dst # on_ finishH (k (Right unit))
pure $ effectCanceler do
Stream.destroy res
Stream.destroy dst
Stream.destroy src
Loading
Loading