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

Remove the non-deterministic module export modification in native.ts #391

Merged
merged 15 commits into from
Sep 8, 2022
Merged
2 changes: 1 addition & 1 deletion script/build.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
aminya marked this conversation as resolved.
Show resolved Hide resolved
set -e

ZMQ_VERSION=${ZMQ_VERSION:-"4.3.4"}
Expand Down
4 changes: 2 additions & 2 deletions script/ci/alpine-chroot-install.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
# https://github.com/alpinelinux/alpine-chroot-install/blob/master/alpine-chroot-install
# vim: set ts=4:
#---help---
Expand Down Expand Up @@ -389,4 +389,4 @@ cat >&2 <<-EOF
---
Alpine installation is complete
Run $CHROOT_DIR/enter-chroot [-u <user>] [command] to enter the chroot.
EOF
EOF
2 changes: 1 addition & 1 deletion script/lint.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
if [ -z "$CI" ]; then
if command -v clang-format >/dev/null; then
echo "Clang-format..."
Expand Down
26 changes: 14 additions & 12 deletions src/draft.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import {methods, Socket, SocketType} from "./native"
import {Socket, SocketType} from "./native"

import {Message, MessageLike, Readable, SocketOptions, Writable} from "."

const {send, receive, join, leave} = methods
import {allowMethods} from "./util"

export class Server extends Socket {
constructor(options?: SocketOptions<Server>) {
Expand All @@ -17,7 +16,7 @@ interface ServerRoutingOptions {
export interface Server
extends Readable<[Message, ServerRoutingOptions]>,
Writable<MessageLike, [ServerRoutingOptions]> {}
Object.assign(Server.prototype, {send, receive})
allowMethods(Server.prototype, ["send", "receive"])

export class Client extends Socket {
constructor(options?: SocketOptions<Client>) {
Expand All @@ -26,7 +25,7 @@ export class Client extends Socket {
}

export interface Client extends Readable<[Message]>, Writable<MessageLike> {}
Object.assign(Client.prototype, {send, receive})
allowMethods(Client.prototype, ["send", "receive"])

export class Radio extends Socket {
constructor(options?: SocketOptions<Radio>) {
Expand All @@ -40,7 +39,10 @@ interface RadioGroupOptions {

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface Radio extends Writable<MessageLike, [RadioGroupOptions]> {}
Object.assign(Radio.prototype, {send})
allowMethods(Radio.prototype, ["send"])

const join = (Socket.prototype as any).join
const leave = (Socket.prototype as any).leave

export class Dish extends Socket {
constructor(options?: SocketOptions<Dish>) {
Expand All @@ -52,13 +54,13 @@ export class Dish extends Socket {

join(...values: Array<Buffer | string>): void {
for (const value of values) {
join.call(this, value)
join(value)
}
}

leave(...values: Array<Buffer | string>): void {
for (const value of values) {
leave.call(this, value)
leave(value)
}
}
}
Expand All @@ -69,7 +71,7 @@ interface DishGroupOptions {

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface Dish extends Readable<[Message, DishGroupOptions]> {}
Object.assign(Dish.prototype, {receive})
allowMethods(Dish.prototype, ["receive", "join", "leave"])

export class Gather extends Socket {
constructor(options?: SocketOptions<Gather>) {
Expand All @@ -81,7 +83,7 @@ export interface Gather extends Readable<[Message]> {
conflate: boolean
}

Object.assign(Gather.prototype, {receive})
allowMethods(Gather.prototype, ["receive"])

export class Scatter extends Socket {
constructor(options?: SocketOptions<Scatter>) {
Expand All @@ -93,7 +95,7 @@ export interface Scatter extends Writable<MessageLike> {
conflate: boolean
}

Object.assign(Scatter.prototype, {send})
allowMethods(Scatter.prototype, ["send"])

export class Datagram extends Socket {
constructor(options?: SocketOptions<Datagram>) {
Expand All @@ -104,4 +106,4 @@ export class Datagram extends Socket {
export interface Datagram
extends Readable<[Message, Message]>,
Writable<[MessageLike, MessageLike]> {}
Object.assign(Datagram.prototype, {send, receive})
allowMethods(Datagram.prototype, ["send", "receive"])
29 changes: 14 additions & 15 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import {allowMethods} from "./util"

export {
capability,
context,
Expand All @@ -14,7 +16,6 @@ export {

import {
capability,
methods,
Context,
EventOfType,
EventType,
Expand All @@ -29,8 +30,6 @@ import {
import * as draft from "./draft"
import {FullError} from "./errors"

const {send, receive} = methods

/**
* A type representing the messages that are returned inside promises by
* {@link Readable.receive}().
Expand Down Expand Up @@ -976,7 +975,7 @@ export class Pair extends Socket {
}

export interface Pair extends Writable, Readable {}
Object.assign(Pair.prototype, {send, receive})
allowMethods(Pair.prototype, ["send", "receive"])

/**
* A {@link Publisher} socket is used to distribute data to {@link Subscriber}s.
Expand Down Expand Up @@ -1028,7 +1027,7 @@ export class Publisher extends Socket {

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface Publisher extends Writable {}
Object.assign(Publisher.prototype, {send})
allowMethods(Publisher.prototype, ["send"])

/**
* A {@link Subscriber} socket is used to subscribe to data distributed by a
Expand Down Expand Up @@ -1128,7 +1127,7 @@ export class Subscriber extends Socket {

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface Subscriber extends Readable {}
Object.assign(Subscriber.prototype, {receive})
allowMethods(Subscriber.prototype, ["receive"])

/**
* A {@link Request} socket acts as a client to send requests to and receive
Expand Down Expand Up @@ -1198,7 +1197,7 @@ export class Request extends Socket {
}

export interface Request extends Readable, Writable {}
Object.assign(Request.prototype, {send, receive})
allowMethods(Request.prototype, ["send", "receive"])

/**
* A {@link Reply} socket can act as a server which receives requests from and
Expand All @@ -1223,7 +1222,7 @@ export class Reply extends Socket {
}

export interface Reply extends Readable, Writable {}
Object.assign(Reply.prototype, {send, receive})
allowMethods(Reply.prototype, ["send", "receive"])

/**
* A {@link Dealer} socket can be used to extend request/reply sockets. Each
Expand Down Expand Up @@ -1280,7 +1279,7 @@ export class Dealer extends Socket {
}

export interface Dealer extends Readable, Writable {}
Object.assign(Dealer.prototype, {send, receive})
allowMethods(Dealer.prototype, ["send", "receive"])

/**
* A {@link Router} can be used to extend request/reply sockets. When receiving
Expand Down Expand Up @@ -1380,7 +1379,7 @@ interface RouterConnectOptions {
}

export interface Router extends Readable, Writable {}
Object.assign(Router.prototype, {send, receive})
allowMethods(Router.prototype, ["send", "receive"])

/**
* A {@link Pull} socket is used by a pipeline node to receive messages from
Expand All @@ -1405,7 +1404,7 @@ export interface Pull extends Readable {
conflate: boolean
}

Object.assign(Pull.prototype, {receive})
allowMethods(Pull.prototype, ["receive"])

/**
* A {@link Push} socket is used by a pipeline node to send messages to
Expand Down Expand Up @@ -1436,7 +1435,7 @@ export interface Push extends Writable {
conflate: boolean
}

Object.assign(Push.prototype, {send})
allowMethods(Push.prototype, ["send"])

/**
* Same as {@link Publisher}, except that you can receive subscriptions from the
Expand Down Expand Up @@ -1516,7 +1515,7 @@ export class XPublisher extends Socket {
}

export interface XPublisher extends Readable, Writable {}
Object.assign(XPublisher.prototype, {send, receive})
allowMethods(XPublisher.prototype, ["send", "receive"])

/**
* Same as {@link Subscriber}, except that you subscribe by sending subscription
Expand All @@ -1532,7 +1531,7 @@ export class XSubscriber extends Socket {
}

export interface XSubscriber extends Readable, Writable {}
Object.assign(XSubscriber.prototype, {send, receive})
allowMethods(XSubscriber.prototype, ["send", "receive"])

/**
* A {@link Stream} is used to send and receive TCP data from a non-ØMQ peer
Expand Down Expand Up @@ -1590,7 +1589,7 @@ interface StreamConnectOptions {
export interface Stream
extends Readable<[Message, Message]>,
Writable<[MessageLike, MessageLike]> {}
Object.assign(Stream.prototype, {send, receive})
allowMethods(Stream.prototype, ["send", "receive"])

/* Meta functionality to define new socket/context options. */
const enum Type {
Expand Down
22 changes: 0 additions & 22 deletions src/native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,6 @@
const path = require("path")
module.exports = require("node-gyp-build")(path.join(__dirname, ".."))

/* We are removing public methods from the Socket prototype that do not apply
to all socket types. We will re-assign them to the prototypes of the
relevant sockets later. For send/receive it is important that they are not
wrapped in JS methods later, to ensure best performance. Any changes to
their signatures should be handled in C++ exclusively. */
interface SpecializedMethods {
send: Function
receive: Function
join: Function
leave: Function
}

const sack: Partial<SpecializedMethods> = {}
const target: SpecializedMethods = module.exports.Socket.prototype
for (const key of ["send", "receive", "join", "leave"] as const) {
sack[key] = target[key]
delete target[key]
}

module.exports.methods = sack
export declare const methods: SpecializedMethods

/**
* The version of the ØMQ library the bindings were built with. Formatted as
* `(major).(minor).(patch)`. For example: `"4.3.2"`.
Expand Down
2 changes: 1 addition & 1 deletion src/socket.cc
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ void Socket::WarnUnlessImmediateOption(int32_t option) const {

if (immediate.count(option) != 0) return;
if (endpoints == 0 && state == State::Open) return;
Warn(Env(), "Socket option will not take effect until next connect/bind.");
// Warn(Env(), "Socket option will not take effect until next connect/bind.");
aminya marked this conversation as resolved.
Show resolved Hide resolved
}

bool Socket::ValidateOpen() const {
Expand Down
17 changes: 17 additions & 0 deletions src/util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// A union type of possible socket method names to leave available from the native Socket.prototype
type SocketMethods = "send" | "receive" | "join" | "leave"

/**
* This function is used to remove the given methods from the given socket_prototype
* to make the relevant socket types have only their relevant methods.
* @param socketPrototype
* @param methods
*/
export function allowMethods(socketPrototype: any, methods: SocketMethods[]) {
const toDelete = ["send", "receive", "join", "leave"] as SocketMethods[]
for (const method of toDelete) {
if (methods.includes(method)) {
delete socketPrototype[method]
}
}
}