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

(asys) API #8832

Open
wants to merge 7 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
8 changes: 8 additions & 0 deletions std/asys/CurrentProcess.hx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ class CurrentProcess {
static var ipcOut:IpcSerializer;
static var ipcIn:IpcUnserializer;

/**
Environment variables, as available to the process when it was created.
This map can be modified, but the changes will only be visible within the
current process. Use `asys.System.setEnv` to make modifications which will
be available in other processes in the same shell.
**/
public static var environment(default, null):Map<String, String>;

/**
Initialise the IPC channel on the given file descriptor `fd`. This should
only be used when the current process was spawned with `Process.spawn` from
Expand Down
5 changes: 4 additions & 1 deletion std/asys/FileAccessMode.hx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ enum abstract FileAccessMode(Int) {
var Write = 1 << 1;
var Read = 1 << 2;

inline function new(value:Int)
this = value;

inline function get_raw():Int return this;

@:op(A | B)
inline function join(other:FileAccessMode) return this | other.get_raw();
inline function join(other:FileAccessMode):FileAccessMode return new FileAccessMode(this | other.get_raw());
}
18 changes: 8 additions & 10 deletions std/asys/FileSystem.hx
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,6 @@ extern class FileSystem {
If `path` points to a symbolic link, this function will change the
permissions of the target file, not the symbolic link itself, unless
`followSymLinks` is set to `false`.

TODO: `followSymLinks == false` is not implemented and will throw.
**/
static function chown(path:FilePath, uid:Int, gid:Int, ?followSymLinks:Bool = true):Void;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it recursive?


Expand Down Expand Up @@ -131,7 +129,7 @@ extern class FileSystem {
/**
Opens the file located at `path`.
**/
static function open(path:FilePath, ?flags:FileOpenFlags /* a */, ?mode:FilePermissions /* 0666 */, ?binary:Bool = true):File;
static function open(path:FilePath, ?flags:FileOpenFlags /* a */, ?mode:FilePermissions /* 0666 */):File;

/**
Reads the contents of a directory specified by `path`. Returns an array of
Expand Down Expand Up @@ -168,6 +166,13 @@ extern class FileSystem {
**/
static function rename(oldPath:FilePath, newPath:FilePath):Void;

/**
Resizes the file located at `path` to exactly `len` bytes. If the file was
larger than `len` bytes, the extra data is lost. If the file was smaller
than `len` bytes, the file is extended with null bytes.
**/
static function resize(path:FilePath, ?len:Int = 0):Void;

/**
Deletes the directory located at `path`. If the directory is not empty or
cannot be deleted, an error is thrown.
Expand All @@ -190,13 +195,6 @@ extern class FileSystem {
**/
static function symlink(target:FilePath, path:FilePath, ?type:SymlinkType = SymlinkType.SymlinkDir):Void;

/**
Truncates the file located at `path` to exactly `len` bytes. If the file was
larger than `len` bytes, the extra data is lost. If the file was smaller
than `len` bytes, the file is extended with null bytes.
**/
static function truncate(path:FilePath, ?len:Int = 0):Void;

/**
Deletes the file located at `path`.
**/
Expand Down
4 changes: 2 additions & 2 deletions std/asys/Net.hx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class Net {
**/
public static function createConnection(options:SocketCreationOptions, ?cb:Callback<NoData>):Socket {
var socket = Socket.create(options);
if (options.connect != null)
if (options != null && options.connect != null)
switch (options.connect) {
case Tcp(options):
socket.connectTcp(options, cb);
Expand All @@ -59,7 +59,7 @@ class Net {
**/
public static function createServer(?options:ServerCreationOptions, ?listener:Listener<Socket>):Server {
var server = new Server(options);
if (options.listen != null)
if (options != null && options.listen != null)
switch (options.listen) {
case Tcp(options):
server.listenTcp(options, listener);
Expand Down
138 changes: 92 additions & 46 deletions std/asys/Process.hx
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,85 @@ import asys.uv.UVProcessSpawnFlags;

/**
Options for spawning a process. See `Process.spawn`.

Either `stdio` or some of `stdin`, `stdout`, and `stderr` can be used define
the file descriptors for the new process:

- `Ignore` - skip the current position. No stream or pipe will be open for
this index.
- `Inherit` - inherit the corresponding file descriptor from the current
process. Shares standard input, standard output, and standard error in
index 0, 1, and 2, respectively. In index 3 or higher, `Inherit` has the
same effect as `Ignore`.
- `Pipe(readable, writable, ?pipe)` - create or use a pipe. `readable` and
`writable` specify whether the pipe will be readable and writable from
the point of view of the spawned process. If `pipe` is given, it is used
directly, otherwise a new pipe is created.
- `Ipc` - create an IPC (inter-process communication) pipe. Only one may be
specified in `options.stdio`. This special pipe will not have an entry in
the `stdio` array of the resulting process; instead, messages can be sent
using the `send` method, and received over `messageSignal`. IPC pipes
allow sending and receiving structured Haxe data, as well as connected
sockets and pipes.
**/
typedef ProcessSpawnOptions = {
/**
Path to the working directory. Defaults to the current working directory if
not given.
**/
?cwd:FilePath,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "short notation" of structs doesn't support doc comments.

/**
Environment variables. Defaults to the environment variables of the current
process if not given.
**/
?env:Map<String, String>,
/**
First entry in the `argv` array for the spawned process. Defaults to
`command` if not given.
**/
?argv0:String,
/**
Array of `ProcessIO` specifications, see `Process.spawn`. Must be `null` if
any of `stdin`, `stdout`, or `stderr` are specified.
**/
?stdio:Array<ProcessIO>,
Aurel300 marked this conversation as resolved.
Show resolved Hide resolved
/**
`ProcessIO` specification for file descriptor 0, the standard input. Must
be `null` if `stdio` is specified.
**/
?stdin:ProcessIO,
/**
`ProcessIO` specification for file descriptor 1, the standard output. Must
be `null` if `stdio` is specified.
**/
?stdout:ProcessIO,
/**
`ProcessIO` specification for file descriptor 2, the standard error. Must
be `null` if `stdio` is specified.
**/
?stderr:ProcessIO,
/**
When `true`, creates a detached process which can continue running after
the current process exits. Note that `unref` must be called on the spawned
process otherwise the event loop of the current process is kept alive.
**/
?detached:Bool,
/**
User identifier.
**/
?uid:Int,
/**
Group identifier.
**/
?gid:Int,
// ?shell:?,
/**
(Windows only.) Do not perform automatic quoting or escaping of arguments.
**/
?windowsVerbatimArguments:Bool,
/**
(Windows only.) Automatically hide the window of the spawned process.
**/
?windowsHide:Bool
};

Expand All @@ -30,27 +98,8 @@ typedef ProcessSpawnOptions = {
class Process {
/**
Execute the given `command` with `args` (none by default). `options` can be
specified to change the way the process is spawned.

`options.stdio` is an optional array of `ProcessIO` specifications which
can be used to define the file descriptors for the new process:

- `Ignore` - skip the current position. No stream or pipe will be open for
this index.
- `Inherit` - inherit the corresponding file descriptor from the current
process. Shares standard input, standard output, and standard error in
index 0, 1, and 2, respectively. In index 3 or higher, `Inherit` has the
same effect as `Ignore`.
- `Pipe(readable, writable, ?pipe)` - create or use a pipe. `readable` and
`writable` specify whether the pipe will be readable and writable from
the point of view of the spawned process. If `pipe` is given, it is used
directly, otherwise a new pipe is created.
- `Ipc` - create an IPC (inter-process communication) pipe. Only one may be
specified in `options.stdio`. This special pipe will not have an entry in
the `stdio` array of the resulting process; instead, messages can be sent
using the `send` method, and received over `messageSignal`. IPC pipes
allow sending and receiving structured Haxe data, as well as connected
sockets and pipes.
specified to change the way the process is spawned. See
`ProcessSpawnOptions` for a description of the options.

Pipes are made available in the `stdio` array after the process is
spawned. Standard file descriptors have their own variables:
Expand All @@ -65,24 +114,6 @@ class Process {
If `options.stdio` is not given,
`[Pipe(true, false), Pipe(false, true), Pipe(false, true)]` is used as a
default.

@param options.cwd Path to the working directory. Defaults to the current
working directory if not given.
@param options.env Environment variables. Defaults to the environment
variables of the current process if not given.
@param options.argv0 First entry in the `argv` array for the spawned
process. Defaults to `command` if not given.
@param options.stdio Array of `ProcessIO` specifications, see above.
@param options.detached When `true`, creates a detached process which can
continue running after the current process exits. Note that `unref` must
be called on the spawned process otherwise the event loop of the current
process is kept allive.
@param options.uid User identifier.
@param options.gid Group identifier.
@param options.windowsVerbatimArguments (Windows only.) Do not perform
automatic quoting or escaping of arguments.
@param options.windowsHide (Windows only.) Automatically hide the window of
the spawned process.
**/
extern public static function spawn(command:String, ?args:Array<String>, ?options:ProcessSpawnOptions):Process;

Expand All @@ -91,7 +122,11 @@ class Process {
**/
public final closeSignal:Signal<NoData> = new ArraySignal();

// public final disconnectSignal:Signal<NoData> = new ArraySignal(); // IPC
/**
Emitted when `this` process disconnects from the IPC channel, if one was
established.
**/
public final disconnectSignal:Signal<NoData> = new ArraySignal();

/**
Emitted when an error occurs during communication with `this` process.
Expand All @@ -109,8 +144,16 @@ class Process {
**/
public var messageSignal(default, null):Signal<IpcMessage>;

/**
`true` when IPC communication is available, indicating that messages may be
received with `messageSignal` and sent with `send`.
**/
public var connected(default, null):Bool = false;
public var killed:Bool;

/**
Set to `true` if the `kill` was used to send a signal to `this` process.
**/
public var killed(default, null):Bool = false;

extern private function get_pid():Int;

Expand Down Expand Up @@ -144,11 +187,10 @@ class Process {
**/
public var stdio:Array<Socket>;

var ipc:Socket;
var ipcOut:asys.io.IpcSerializer;
var ipcIn:asys.io.IpcUnserializer;

// public function disconnect():Void; // IPC
/**
Disconnect `this` process from the IPC channel.
**/
extern public function disconnect():Void;

/**
Send a signal to `this` process.
Expand All @@ -174,5 +216,9 @@ class Process {

extern public function unref():Void;

var ipc:Socket;
var ipcOut:asys.io.IpcSerializer;
var ipcIn:asys.io.IpcUnserializer;

private function new() {}
}
15 changes: 15 additions & 0 deletions std/asys/System.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package asys;

extern class System {
/**
Returns the current value of the environment variable `name`, or `null` if
it does not exist.
**/
public static function getEnv(name:String):Null<String>;

/**
Sets the value of the environment variable `name` to `value`. If `value` is
`null`, the variable is deleted.
**/
public static function setEnv(name:String, value:Null<String>):Void;
}
2 changes: 1 addition & 1 deletion std/asys/io/IpcMessage.hx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ typedef IpcMessage = {
The actual message. May be any data that is serializable with
`haxe.Serializer`.
**/
var message:Dynamic;
var message:Any;
/**
Sockets and pipes associated with the message. Must be connected.
**/
Expand Down
5 changes: 4 additions & 1 deletion std/asys/net/Socket.hx
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,13 @@ class Socket extends Duplex {
}

/**
Emitted when the socket connects to a remote endpoint.
Emitted when the handle is closed.
**/
public final closeSignal:Signal<NoData> = new ArraySignal();

/**
Emitted when the socket connects to a remote endpoint.
**/
public final connectSignal:Signal<NoData> = new ArraySignal();

// endSignal
Expand Down
12 changes: 6 additions & 6 deletions std/haxe/async/ArraySignal.hx
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ class ArraySignal<T> implements Signal<T> {
});
}

public function off(?listener:Listener<T>):Void {
if (listener != null) {
listeners.remove(listener);
} else {
listeners.resize(0);
}
public function off(listener:Listener<T>):Void {
listeners.remove(listener);
}

public function clear():Void {
listeners.resize(0);
}

public function emit(data:T):Void {
Expand Down
4 changes: 2 additions & 2 deletions std/haxe/async/Defer.hx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class Defer {
Schedules the given function to run during the next processing tick.
Convenience shortcut for `Timer.delay(f, 0)`.
**/
public static inline function nextTick(f:() -> Void):asys.Timer {
return asys.Timer.delay(f, 0);
public static inline function nextTick(f:() -> Void):haxe.Timer {
return haxe.Timer.delay(f, 0);
}
}
7 changes: 6 additions & 1 deletion std/haxe/async/Signal.hx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ interface Signal<T> {
/**
Removes the given listener from `this` signal.
**/
function off(?listener:Listener<T>):Void;
function off(listener:Listener<T>):Void;

/**
Removes all listeners from `this` signal.
**/
function clear():Void;

/**
Emits `data` to all current listeners of `this` signal.
Expand Down
13 changes: 7 additions & 6 deletions std/haxe/async/WrappedSignal.hx
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,13 @@ class WrappedSignal<T> implements Signal<T> {
changeSignal.emit(new NoData());
}

public function off(?listener:Listener<T>):Void {
if (listener != null) {
listeners.remove(listener);
} else {
listeners.resize(0);
}
public function off(listener:Listener<T>):Void {
listeners.remove(listener);
changeSignal.emit(new NoData());
}

public function clear():Void {
listeners.resize(0);
changeSignal.emit(new NoData());
}

Expand Down
Loading