All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog and this project adheres to Semantic Versioning.
- Global JavaScript modules not compiling correctly
ElixirScript.Test
for testing ElixirScript modules in JavaScript. ElixirScript.Test is for unit testing modules that interact with JavaScript in some way. For modules that are can be used in both Elixir and ElixirScript, ExUnit is still preferred. Tests that use ElixirScript.Test must be placed in atest_elixir_script
folder in the root of your project. These tests are run using node.js. The API for ElixirScript.Test is meant to be as close to ExUnit as possible.
-
ElixirScript now requires Elixir 1.6. This is so that ElixirScript can use the new
Mix.Task.Compiler
behaviour. -
mix clean
will now correctly clean up ElixirScript output. -
Compiler will now output a JavaScript file per Elixir module.
-
Modules with a start function must be started directly.
# Before ElixirScript 0.32.0: import Elixir from './elixirscript.build.js' Elixir.start(Elixir.Main, [1, 2, 3]) # ElixirScript 0.32.0 and later: import Main from './Elixir.Main.js' Main.start(Symbol.for('normal'), [1, 2, 3])
- Compiler error when
receive
is used as variable name
- Compiler will now accept a path to Elixir Files to compile
- Added
ElixirScript.JS.map_to_object/2
with options [keys: :string, symbols: false] - Added
ElixirScript.JS.object_to_map/1|2
with options [keys: :atom, recurse_array: true] - Fully implement
__info__
on modules - Concurrent Compilation
- The following erlang functions have been implemented:
- :erlang.nodes/0
- :erlang.nodes/1
- :math.log2/1
- :binary.copy/1
- :binary.copy/2
- :binary.part/2
- :binary.part/3
- :binary.replace/3
- :binary.replace/4 (some options still missing)
- Make sure not to add underscores to erlang functions
- Make sure any variable names that are javascript keywords are handled properly
- Make sure variables that begin with
_
are available - Finding the use of functions within anonymous functions
- Reimplement
String.split_at/2
to make sure Unicode library isn't compiled - byte_size does not work on binaries that started via "" elixir string syntax
- using . (dot) reference syntax on a map fails when value is a function
- Make sure that remote ast works correctly with variables
- Make sure == works as expected
- Make sure that erlang function names that are also JavaScript keywords are not filters
- erlang.error now throws errors resembling those in Elixir
- Map.get fails if key is tuple or list
- ElixirScript now has a Foreign Function Interface (FFI) for interoperability with JavaScript. For more details, see documentation at
ElixirScript.FFI
ElixirScript.JS.mutate/3
ElixirScript.JS.map_to_object/1
root
option for specifying the root import path for FFI JavaScript modules. Defaults to"."
- Compiler has been completely rewritten. ElixirScript now requires Erlang 20+ and Elixir 1.5+
JS
module renamed toElixirScript.JS
- Default output path is now
priv/elixir_script/build
- Support for CommonJS and UMD output formats has been removed. Output will be in ES module format
- The
js_modules
option has been removed in favor of the new FFI - ElixirScript.Watcher has been removed
remove-unused
option that will remove all unused modules from output- reimplemented structs to avoid creating JavaScript classes
super
defoverridable
IO.inspect\1
,IO.puts\1
,IO.puts\2
,IO.warn\1
Elixir.load
for loading generated JavaScript modules in bundled output. UnlikeElixir.start
, this will only call__load
on the module and return the functions on it
const exports = Elixir.load(Elixir.MyApp);
exports.hello();
-ex
alias is now-e
- A filename can be specified for output
- To access global JavaScript functions, modules, and properties, use the
JS
module
JS.length # translates to 'length'
JS.alert() # translates to 'alert()'
JS.String.raw("hi") # translate to String.raw('hi')
JS.console.log("hi") # translates to console.log('hi')
- Make sure mix compiler works in umbrella apps
- Fixed
for
translation - Updated documentation
-
Multiple
when
clauses in guards -
Kernel.defdelegate/2
-
js_modules
configuration option has been added. This is a list of JavaScript modules that will be used.js_modules: [ {React, "react"}, {ReactDOM, "react-dom"} ]
-
js-module
flag has been added to the CLI in order to pass js modules.
elixirscript "app/elixirscript" -o dist --js-module React:react --js-module ReactDOM:react-dom
@on_js_load
has been removed in favor of having astart/2
function defined. More info belowJS.import
has been removed in favor of defining JavaScript modules used in configuration
-
Now bundles all output, including the boostrap code. The exported object has Elixir modules in JavaScript namespaces that are lazily loaded when called.
To start your application import the bundle according to whichever module format was selected and then call start giving it the module and the initial args
//ES module example import Elixir from './Elixir.App'; Elixir.start(Elixir.App, []);
The
start
function will look for astart/2
function there. This is analogous to a Application module callback
-
Updated elixir_script mix compiler to support compiling elixir_script paths in dependencies if dependency has mix compiler defined as well
-
Add
Collectable
protocol implementations -
Updated
for
implementation to useCollectable
-
format
option. Can now specify the module format of output. Choices are: _:es
(default) for ES Modules _:umd
for UMD *:common
for CommonJS -
Default input, output and format for elixirscript mix compiler. In a mix project by default the elixirscript compiler will look in
lib/elixirscript
and input and place output inpriv/elixirscript
. The default format is:es
receive
Process
module
- JS module functions not translated properly when imported
- Update fs dependency to 2.12
- Incorrect handling of function heads with guards
- Support for
sigil_r
Regex
module- Better JavaScript formatting
- CLI now allows a comma-separated or space-separated list of paths
- Struct not properly referenced
- Tail call optimization
@load_only
: lets the compiler know to load in the module, but not to compile it
- Agent not functioning properly. Now uses internal store instead of making a process and using that to put data in store
- Protocol incorrectly handling strings
defgen
anddefgenp
functions not being recognized by Elixir compiler.
- Incorrectly sending standard lib when using compile or compile_path by default
-
New compiler pipeline
-
@on_js_load
. Expects a 0 arity function. This function will be called when the compiled module is loaded in JavaScript -
JS.import\3
. Just likeJS.import\2
but expects options to decide if the import should be a default one or a namespace on. Only option allowed isdefault
. Set totrue
by default# translates to "import A from 'a'" JS.import A, "a" #translates to "import * as A from 'a'" JS.import A, "a", default: false
- The form of
JS.import
that accepted a list of atoms as the first arg. UsedJS.import\3
withdefault: false
instead to create a namespace import env
androot
are no longer options forElixirScript
's compile functions and cli- Syntax once supported by Elixirscript
JQuery.("#element")
, is no longer supported
-
Changed CHANGELOG.md to adhere the format from Keep a Changelog
-
defmacro
now supported. No longer have to separate macros from functions in separate files.defmacrop
still unsupported -
To use anything in the
JS
module, you mustrequire
theJS
module first -
Elixirscript files must now contain valid Elixir syntax.
-
Now compiles
exjs
andex
files within the path can be compiled all the same. Dependencies from hex are still unsupported so these files must not rely on any code outside of the path. What this does mean is that it is now possible to share code between Elixir and Elixirscript as long as the Elixir files functionality fall within what Elixirscript currently supports. -
defgen
,defgenp
,yield
,yield_to
, andobject
are now in theJS
module -
To access functions in the global JavaScript scope, either use
JS.global\0
or use the erlang module call syntax#calling alert JS.global().alert("hi") #calling alert :window.alert("hi")
Calling JavaScript modules in the global scope works without using the above methods
#calls window.Date.now() Date.now()
defgen
anddefgenp
for defining public and private generatorsyield/0
,yield/1
, andyield_to\1
toKernel
- Updated output folder structure. stdlib code will now go in an
elxiir
folder under the output paths while generated app code will go into anapp
folder under the output path - All process macros and functions now expect to receive and/or work using generators as entry points. Using functions defined with
def
ordefp
will not work correctly with them
- Correctly returning list if list is only item in body
- This is the first release with early support for processes in elixirscript. Creating a process only works currently using
spawn/1
,spawn_link/1
, andspawn_monitor/1
. Inside of a process, you can use functions such assend
andreceive
, along with some defined in theProcess
module. From outside of a process, you can send messages to a process, but you cannot receive a message from a process. Eventually all code will run inside processes and this restriction will naturally lift. - The
Process
module has been implemented with the following functions:alive?/1
delete/1
demonitor/1
exit/2
flag/2
flag/3
get/0
get_keys/0
get_keys/1
link/1
list/0
monitor/1
put/2
register/2
registered/0
send/3
sleep/1
unlink/1
unregister/1
whereis/1
- The
receive
special form has been implemented with the above caveat - The following have been implemented on
Kernel
:spawn/1
spawn_link/1
spawn_monitor/1
send/2
make_ref/0
- Scoping on
fn
anddef
ElixirScript.Watcher
module andelixirscript.watch
mix task- logging MatchError exceptions to better show terms that don't match
- elixir_script mix compiler
Html
,View
, andVDom
modules have been removed
- Better support for macros. Macros should be defined in .ex or .exs files. ElixirScript code should be in .exjs files
NOTE: The above functionality will cause either compiler errors or no output. Please change extensions of ElixirScript code to .exjs
Html
,View
, andVDom
modules will be removed in the next version as they can now be replicated using macros
output
as an option for compiler functions. This controls whether output is returned as a list of tuples, send to stdout, or saved to a file path:full_build
as an option for compiler functions and--full-build
option to CLI. These force the compiler to perform a full build--version
option to CLI. Outputs current version of elixirscript--std-lib
option to CLI. Takes a path and adds the stdlib to that path
- Renamed
copy_core_to_destination
tocopy_stdlib_to_destination
- Incremental Compilation: ElixirScript will now only build files and modules that have changed since the last build
--core
option from CLI and:core
compiler option.
-
Bitstring pattern matching
-
Bitstrings in for comprehensions
-
Functions with catch, after, else clauses
-
with
special form -
Pin operator in map keys and function clauses
-
Added
Kernel.object/1
function to make it more natural to create a JavaScript object with string keys. Elixirscript, by default turns the following,%{a:"b"}
into{[Symbol.for("a")]: "b"}
in JavaScript. In order to get string keys, one would have to do%{"a" => "b"}
which turns into{a: "b"}
in JavaScript. WithKernel.object
, you can create string keyed maps conveniently,object(a: "b")
which turns into{a: "b"}
.NOTE: when updating the created by, you still have to use the string form
%{ my_map | "a" => "c" }
JS.update(object, property, value)
has been removed and replaced withJS.update(object, map)
. This allows you to update multiple values on a javascript object at once.
- Optional parameters should now work as expected
- Support for variables as map keys
- Protocol implementations for Integer and Float which where not recognized
- Calling properties on non-objects
- Removed
catch
as a javascript keyword to filter
- Fixed View module so that an element can have multiple elements within
- struct implementation so that lists of atoms for fields are compiled correctly
- head-tail pattern match to allow for more complicated scenarios
- ModuleCollector to properly alias inner modules
- Raise translation to properly translate when string messages are given
__ENV__
and__CALLER__
are now supportedJS.import/1
,JS.typeof/1
,JS.instanceof/1
, andJS.global/1
- Support for multi alias/require/imports statements
alias
,require
, andimport
now work inside lexical scopes- Some of the standard library originally written in JavaScript has been rewritten in Elixir.
- Generated JavaScript export statements are now default exports
- When output is sent to standard out, there are now markers to specify where each module begins as well as what the file name would be. For the end of a file,
//:ENDFILE
is used. For the file name,//<file>:ENDFILENAME
is used where<file>
is the name of the file compile
,compile_path
, andcompile_quoted
opts parameter now expects a map- The
stdlib
compiler option is nowcore
. Thestdlib_path
compiler options is nowcore_path
- .DS_Store and LICENSE from output
- Can now implement protocols using JavaScript types
defimpl MyProtocol, for: HTMLElement
- virtual-dom JavaScript library
- ElixirScript.Html module for defining a virtual-dom tree
- ElixirScript.VDom module for manipulating the virtual-dom tree created using the ElixirScript.Html module
- Added ElixirScript.View module for handling view state and rendering virtual-dom
- Added
stdlib_path
compiler option to specify the es6 path to the standard library. If used, elixir.js will not be exported with the compiled modules
- Renamed
ex2js
toelixirscript
. This effects the escript as well as the mix task - Structs are now translated into classes
- Structs and Tuples now match on their types
- Can now match on JavaScript classes. Works just like matching on structs:
def my_func(%HTMLElement{id: "myId"})
- Moved non-elixir JavaScript code into
core
es6 module. This will hopefully make it so ElixirScript Standard Library modules can be defined in Elixir soon.
Base
module with function: encode64, decode64, and decode64!String
moduleBitwise
moduleMap
moduleMapSet
moduleSet
module- Protocol support
- Added
Collectable
,Enumerable
,Inspect
,List.Chars
, andString.Chars
protocols. The only one currently being used in the Standard Library, however, is String.Chars
- Added PostOffice. Only thing that current uses it is Agent
- Updated tuple implementation. It's now a class.
- Replaced pattern matching library with custom one
- Moved data types to Kernel.SpecialForms
else
now works for try expressions- for now works with
into
for lists
- Removed erlang.js.
- Added
JS
module withnew
,mutate
,import
macros - Added
Keyword
module with functions,has_key?
andget
- Added
Agent
module with functions,start
,get
,update
, andget_and_update
- Map keys are now correctly turned into their atom counterparts if atom keys are used
import
works with all optionsMutable.update
has been replaced byJS.update
transpile
,transpile_quoted
, andtranspile_path
are nowcompile
,compile_quoted
, andcompile_path
- All Standard libraries are rolled up into one elixir.js file and imported from that
- Modules no longer export a default object
alias
now translates to a namespace import unlessdefault
option is given
- Added
env
option forElixirScript.transpile
adding macros for compilation - Added
Logger
that translates Logger functions to console
- Updated
Kernel
module to translate some functions to it's JavaScript equivalent
- Fixed
case
implementation to addthis
to call
- an implementation for quote. Currently ignores
:location
and:context
options - an implementation for unquote and unquote_splicing
- Can now support catch blocks in try expressions
- Added receive
- Updated pattern matching implementation
- Wrapped try's in function closure to make sure they return a value;
- Can now support rescue and after blocks in try expressions
- Now using the JS code generator from elixir-estree for code generation, improving speed of transpilation
- the parse functions in the ElixirScript module have been renamed to transpile
- Added iterators for Range and BitString
- Now replacing characters that can't be used in variable and function names in JavaScript with something that it (i.e.
match?
->match__qmark__
) - Implemented Integer module
- Made the Tuple, Range and BitString data structures more immutable
- Atom now translates to an ES6 Symbol
- List now translates to a frozen JS Array
- Updated the pattern match binding to use ES6 destructuring for lists and tuples
- Inner modules are now split out into their own files
- Standard lib is now exported with file output from cli
- Standard lib modules are now automatically imported
- No longer have to define modules via aliases ahead of time. They will be automatically be resolved and made into JavaScript import statements
- added
from
clause toimport
,alias
, andrequire
so that the import path can be overridden
- For statements now work with pattern matching tuples
- Improved function chaining
alias
now acts likerequire
in that it is translated into an import default statement- modules now export a default object with def functions added as properties on it.
- for function closures, now calling by using
.call(this)
so thatthis
is available inside of it
- bitstrings
- Better Pattern Matching (Does not support bitstrings yet)
- Capture Operator
- Added more functions from the list standard library
- Updated variable implementation to match Elixir's (i.e. Reusing the same variable name creates a new one in the background)
- Fixed multi arity implementation
- function and case guards
- function and case pattern matching
- Can now use ^ on a variable during assignment
- Renamed project to ElixirScript
- Reduced escript file size
- Pipe operator
- String interpolation
- Adding more functions to the Kernel module
- Fully implemented Tuple module
- Fully implemented Atom module
- Fully implemented Range module
- Now checking to see if a function is a Kernel function and prepending Kernel to it
- Now turning Atoms into an Atom javascript object instead of a Symbol
- Now turning tuples into a Tuple javascript object
- Can now call properties and zero parameter functions correctly
- case, cond, and if are now turned into if statements wrapped in function closures
- Anonymous functions are now turned into anonymous functions in javascript insteed of arrow functions
- From standard library implemented:
- Enum.map
- Kernel.tl
- Kernel.hd
- Logger
- Implemented language features:
- All primitives except bitstrings
- defmodule
- import, alias, and require
- case, cond, if
- def, defp
- defstruct, defexception
- raise
- multiple arity functions
- basic binary operations
- for without into