From 3610dff1b8308a810d827f0595832b326deff37b Mon Sep 17 00:00:00 2001 From: eric thul Date: Sat, 18 Jul 2015 17:07:38 -0400 Subject: Add FFI JavaScript as a webpack dependency Resolves #18 --- example/package.json | 6 ++++-- example/src/Test.purs | 4 +++- example/src/TestFFI.js | 7 +++++++ example/src/entry.js | 8 ++++---- example/webpack.config.js | 4 ++-- src/FS.purs | 35 +++++++++++++++++++++++++++++++++++ src/Loader.purs | 23 ++++++++++++++++++++--- src/LoaderRef.purs | 24 ++++++++++++++++++++++++ 8 files changed, 99 insertions(+), 12 deletions(-) create mode 100644 example/src/TestFFI.js diff --git a/example/package.json b/example/package.json index df3e74f..d1319b1 100644 --- a/example/package.json +++ b/example/package.json @@ -3,13 +3,15 @@ "version": "0.0.0", "private": true, "scripts": { - "build": "mkdir -p output && ./node_modules/.bin/webpack", + "build": "mkdir -p output && ./node_modules/.bin/webpack --progress --colors", + "build:watch": "mkdir -p output && ./node_modules/.bin/webpack --progress --colors --watch", "run": "node bundle.js", "clean": "rm -rf bower_components && rm -rf bundle.js && rm -rf node_modules && rm -rf output" }, "license": "MIT", "devDependencies": { + "node-libs-browser": "^0.5.2", "purs-loader": "file:../", - "webpack": "^1.8.4" + "webpack": "^1.10.1" } } diff --git a/example/src/Test.purs b/example/src/Test.purs index d9f1b96..133a192 100644 --- a/example/src/Test.purs +++ b/example/src/Test.purs @@ -1,5 +1,7 @@ -module Test (test) where +module Test (test, testing) where import Prelude test = "a" + +foreign import testing :: String diff --git a/example/src/TestFFI.js b/example/src/TestFFI.js new file mode 100644 index 0000000..dc2f04f --- /dev/null +++ b/example/src/TestFFI.js @@ -0,0 +1,7 @@ +'use strict'; + +// module Test + +var testing = 'abcde'; + +exports.testing = testing; diff --git a/example/src/entry.js b/example/src/entry.js index 344d4c6..a41536c 100644 --- a/example/src/entry.js +++ b/example/src/entry.js @@ -1,11 +1,11 @@ var Prelude = require('Prelude'); -var test = require('./Test'); +var test = require('./Test.purs'); -var foo = require('./Foo'); +var foo = require('./Foo.purs'); -var baz = require('./Foo/Baz'); +var baz = require('./Foo/Baz.purs'); -var bar = require('./Foo/Bar'); +var bar = require('./Foo/Bar.purs'); console.log(Prelude, test, foo, baz, bar); diff --git a/example/webpack.config.js b/example/webpack.config.js index 9294904..1a0eef6 100644 --- a/example/webpack.config.js +++ b/example/webpack.config.js @@ -2,7 +2,7 @@ var path = require('path'); var srcs = ['src[]=bower_components/purescript-*/src/**/*.purs', 'src[]=src/**/*.purs']; -var ffis = ['ffi[]=bower_components/purescript-*/src/**/*.js']; +var ffis = ['ffi[]=bower_components/purescript-*/src/**/*.js', 'ffi[]=src/**/*FFI.js']; var output = 'output'; @@ -22,7 +22,7 @@ var config , loader: 'purs-loader?output=' + output + '&' + srcs.concat(ffis).join('&') } ] } , resolve: { modulesDirectories: modulesDirectories - , extensions: ['', '.js', '.purs'] + , extensions: ['', '.js'] } , resolveLoader: { root: path.join(__dirname, 'node_modules') } } diff --git a/src/FS.purs b/src/FS.purs index a56fe26..6955a63 100644 --- a/src/FS.purs +++ b/src/FS.purs @@ -1,12 +1,16 @@ module PursLoader.FS ( FS() , writeFileUtf8 + , findFileUtf8 ) where import Control.Monad.Aff (Aff(), makeAff) import Control.Monad.Eff (Eff()) import Control.Monad.Eff.Exception (Error()) +import Data.Maybe (Maybe(..)) +import Data.String.Regex (Regex()) + import Data.Function foreign import data FS :: ! @@ -30,3 +34,34 @@ function writeFileUtf8Fn(filepath, contents, errback, callback) { (Error -> Eff (fs :: FS | eff) Unit) (Unit -> Eff (fs :: FS | eff) Unit) (Eff (fs :: FS | eff) Unit) + +findFileUtf8 :: forall eff. Regex -> [String] -> Aff (fs :: FS | eff) (Maybe String) +findFileUtf8 regexp filepaths = makeAff $ runFn6 findFileUtf8Fn Nothing Just regexp filepaths + +foreign import findFileUtf8Fn """ +function findFileUtf8Fn(nothing, just, regex, filepaths, errback, callback) { + return function(){ + var fs = require('fs'); + + var async = require('async'); + + function findFile(filepath, callback) { + fs.readFile(filepath, {encoding: 'utf-8'}, function(error, result){ + if (error) callback(false); + else callback(regex.test(result)); + }); + } + + async.detect(filepaths, findFile, function(result){ + if (!result) callback(nothing)(); + else callback(just(result))(); + }); + }; +} +""" :: forall eff. Fn6 (Maybe String) + (String -> Maybe String) + Regex + [String] + (Error -> Eff (fs :: FS | eff) Unit) + (Maybe String -> Eff (fs :: FS | eff) Unit) + (Eff (fs :: FS | eff) Unit) diff --git a/src/Loader.purs b/src/Loader.purs index 872a51c..e9e03c4 100644 --- a/src/Loader.purs +++ b/src/Loader.purs @@ -13,12 +13,12 @@ import Data.Array ((!!), concat) import Data.Function (Fn2(), mkFn2) import Data.Maybe (Maybe(..), fromMaybe, maybe) import Data.String (joinWith) -import Data.String.Regex (match, noFlags, regex) +import Data.String.Regex (match, noFlags, regex, test) import PursLoader.ChildProcess (ChildProcess(), spawn) -import PursLoader.FS (FS(), writeFileUtf8) +import PursLoader.FS (FS(), writeFileUtf8, findFileUtf8) import PursLoader.Glob (Glob(), globAll) -import PursLoader.LoaderRef (LoaderRef(), Loader(), async, cacheable, query) +import PursLoader.LoaderRef (LoaderRef(), Loader(), async, cacheable, query, clearDependencies, addDependency, resourcePath) import PursLoader.LoaderUtil (parseQuery) import PursLoader.Options (loaderFFIOption, loaderSrcOption, pscOptions) @@ -26,6 +26,8 @@ type Effects eff = (cp :: ChildProcess, fs :: FS, glob :: Glob, loader :: Loader moduleRegex = regex "(?:^|\\n)module\\s+([\\w\\.]+)" noFlags { ignoreCase = true } +foreignRegex = regex "(?:^|\\n)\\s*foreign import\\s+" noFlags { ignoreCase = true } + pscCommand = "psc" psciCommand = "psci" @@ -54,6 +56,11 @@ mkPsci srcs ffis = joinWith "\n" ((loadModule <$> concat srcs) <> (loadForeign < loadForeign :: String -> String loadForeign a = ":f " ++ relative cwd a +findFFI :: forall eff. [[String]] -> String -> Aff (fs :: FS | eff) (Maybe String) +findFFI ffiss name = findFileUtf8 re (concat ffiss) + where + re = regex ("(?:^|\\n)//\\s*module\\s*" ++ name ++ "\\s*\\n") noFlags + loader' :: forall eff. LoaderRef -> String -> Aff (Effects eff) (Maybe String) loader' ref source = do liftEff $ cacheable ref @@ -73,8 +80,18 @@ loader' ref source = do writeFileUtf8 psciFilename psciFile let moduleName = match moduleRegex source >>= (!!!) 1 + hasForeign = test foreignRegex source result = (\a -> "module.exports = require('" ++ a ++ "');") <$> moduleName + liftEff (clearDependencies ref) + liftEff (addDependency ref (resourcePath ref)) + + foreignPath <- if hasForeign + then fromMaybe (pure Nothing) (findFFI ffiss <$> moduleName) + else pure Nothing + + fromMaybe (pure unit) ((\path -> liftEff (addDependency ref path)) <$> foreignPath) + return result loader :: forall eff. LoaderRef -> String -> Eff (Effects eff) Unit diff --git a/src/LoaderRef.purs b/src/LoaderRef.purs index 2567b1e..f1efa04 100644 --- a/src/LoaderRef.purs +++ b/src/LoaderRef.purs @@ -4,6 +4,9 @@ module PursLoader.LoaderRef , async , cacheable , query + , clearDependencies + , addDependency + , resourcePath ) where import Control.Monad.Eff (Eff()) @@ -48,3 +51,24 @@ foreign import query """ function query(ref){ return ref.query; }""" :: LoaderRef -> String + +foreign import clearDependencies """ +function clearDependencies(ref){ + return function(){ + return ref.clearDependencies(); + }; +}""" :: forall eff. LoaderRef -> Eff (loader :: Loader | eff) Unit + +foreign import resourcePath """ +function resourcePath(ref){ + return ref.resourcePath; +}""" :: LoaderRef -> String + +foreign import addDependency """ +function addDependency(ref){ + return function(dep){ + return function(){ + return ref.addDependency(dep); + }; + }; +}""" :: forall eff. LoaderRef -> String -> Eff (loader :: Loader | eff) Unit -- cgit v1.2.3