diff --git a/.idea/libraries/Netty.xml b/.idea/libraries/Netty.xml
index 1c2042bff2df..88514907016d 100644
--- a/.idea/libraries/Netty.xml
+++ b/.idea/libraries/Netty.xml
@@ -1,11 +1,11 @@
-
+
-
+
\ No newline at end of file
diff --git a/lib/io/netty/buffer/annotations.xml b/lib/io/netty/buffer/annotations.xml
new file mode 100644
index 000000000000..d2c4e9fdafff
--- /dev/null
+++ b/lib/io/netty/buffer/annotations.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/lib/io/netty/channel/annotations.xml b/lib/io/netty/channel/annotations.xml
index f3c89814e95a..2c53e34a7c43 100644
--- a/lib/io/netty/channel/annotations.xml
+++ b/lib/io/netty/channel/annotations.xml
@@ -1,4 +1,7 @@
+
+
+
diff --git a/lib/netty-all-4.1.0.Beta3.jar b/lib/netty-all-4.1.0.Beta3.jar
deleted file mode 100644
index fd2f6ba0e6c5..000000000000
Binary files a/lib/netty-all-4.1.0.Beta3.jar and /dev/null differ
diff --git a/lib/netty-all-4.1.0.Beta4.jar b/lib/netty-all-4.1.0.Beta4.jar
new file mode 100644
index 000000000000..8d2c7b135eb4
Binary files /dev/null and b/lib/netty-all-4.1.0.Beta4.jar differ
diff --git a/lib/required_for_dist.txt b/lib/required_for_dist.txt
index cd87b4f01e3a..53deae77108f 100644
--- a/lib/required_for_dist.txt
+++ b/lib/required_for_dist.txt
@@ -48,7 +48,7 @@ microba.jar
miglayout-swing.jar
nanoxml-2.2.3.jar
nekohtml-1.9.14.jar
-netty-all-4.1.0.Beta3.jar
+netty-all-4.1.0.Beta4.jar
oromatcher.jar
picocontainer.jar
protobuf-2.5.0.jar
diff --git a/lib/src/netty-all-4.1.0.Beta3-sources.jar b/lib/src/netty-all-4.1.0.Beta4-sources.jar
similarity index 54%
rename from lib/src/netty-all-4.1.0.Beta3-sources.jar
rename to lib/src/netty-all-4.1.0.Beta4-sources.jar
index 80f203cec58a..fdc336ab6051 100644
Binary files a/lib/src/netty-all-4.1.0.Beta3-sources.jar and b/lib/src/netty-all-4.1.0.Beta4-sources.jar differ
diff --git a/platform/built-in-server-api/src/org/jetbrains/ide/BinaryRequestHandler.java b/platform/built-in-server-api/src/org/jetbrains/ide/BinaryRequestHandler.java
index ebcb2323c4ac..ba616c250603 100644
--- a/platform/built-in-server-api/src/org/jetbrains/ide/BinaryRequestHandler.java
+++ b/platform/built-in-server-api/src/org/jetbrains/ide/BinaryRequestHandler.java
@@ -17,12 +17,13 @@ package org.jetbrains.ide;
import com.intellij.openapi.extensions.ExtensionPointName;
import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
public abstract class BinaryRequestHandler {
- public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.binaryRequestHandler");
+ public static final ExtensionPointName EP_NAME = ExtensionPointName.create("org.jetbrains.binaryRequestHandler");
@NotNull
/**
@@ -31,5 +32,5 @@ public abstract class BinaryRequestHandler {
public abstract UUID getId();
@NotNull
- public abstract ChannelHandler getInboundHandler();
+ public abstract ChannelHandler getInboundHandler(@NotNull ChannelHandlerContext context);
}
\ No newline at end of file
diff --git a/platform/built-in-server/client/node-rpc-client/gulpfile.js b/platform/built-in-server/client/node-rpc-client/gulpfile.js
index 812a2a5dd94c..ea4c5ed0e837 100644
--- a/platform/built-in-server/client/node-rpc-client/gulpfile.js
+++ b/platform/built-in-server/client/node-rpc-client/gulpfile.js
@@ -25,12 +25,12 @@ gulp.task("compile", function () {
.pipe(ts(tsProject));
tsResult.js.pipe(concat(outFile))
- .pipe(uglify({
- output: {
- beautify: true,
- indent_level: 2
- }
- }))
+ //.pipe(uglify({
+ // output: {
+ // beautify: true,
+ // indent_level: 2
+ // }
+ // }))
.pipe(sourcemaps.write('.', {includeContent: false, sourceRoot: path.resolve('testData')}))
.pipe(gulp.dest(outDir))
});
diff --git a/platform/built-in-server/client/node-rpc-client/package.json b/platform/built-in-server/client/node-rpc-client/package.json
index 91cb522d537c..862a64057dac 100644
--- a/platform/built-in-server/client/node-rpc-client/package.json
+++ b/platform/built-in-server/client/node-rpc-client/package.json
@@ -1,7 +1,11 @@
{
"name": "ij-rpc-client",
- "version": 0.1,
+ "version": "0.0.1",
"description": "IntelliJ Platform RPC client",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/JetBrains/intellij-community.git"
+ },
"devDependencies": {
"gulp": "^3.8.11",
"gulp-concat": "^2.4.3",
diff --git a/platform/built-in-server/client/node-rpc-client/src/rpc-client.ts b/platform/built-in-server/client/node-rpc-client/src/rpc-client.ts
index 93f461ed1f96..b8425f3ee9d6 100644
--- a/platform/built-in-server/client/node-rpc-client/src/rpc-client.ts
+++ b/platform/built-in-server/client/node-rpc-client/src/rpc-client.ts
@@ -1,6 +1,7 @@
-///
+"use strict"
import net = require("net")
+import rpc = require("./rpc")
export class RpcClient {
connect(port:Number = 63342) {
@@ -8,92 +9,43 @@ export class RpcClient {
console.log('Connected to IJ RPC server localhost:' + port)
});
- var jsonRpc = new JsonRpc(new Socket(socket))
+ var jsonRpc = new rpc.JsonRpc(new SocketTransport(socket))
var decoder:MessageDecoder = new MessageDecoder(jsonRpc.messageReceived)
socket.on('data', decoder.messageReceived)
}
}
-enum State {LENGTH, CONTENT}
+const enum State {LENGTH, CONTENT}
-class Socket {
- private uint32Buffer = new Buffer(4)
+class SocketTransport implements rpc.Transport {
+ private headerBuffer = new Buffer(4)
constructor(private socket:net.Socket) {
}
- send(message:string) {
- var encoded = new Buffer(message)
- this.uint32Buffer.writeUInt32BE(Buffer.byteLength(message), 0)
- this.socket.write(this.uint32Buffer)
- this.socket.write(message, 'utf-8')
- }
-}
-
-class JsonRpc {
- private messageIdCounter = 0
- private callbacks:Mapvoid> = new Mapvoid>()
- private domains:Map = new Map();
-
- constructor(private socket:Socket) {
+ send(id:number, domain:string, command:string, params:any[] = null):void {
+ var encodedParams = JSON.stringify(params)
+ var header = (id == -1 ? '' : (id + ', ')) + '"' + domain + '", "' + command + '"';
+ this.headerBuffer.writeUInt32BE(Buffer.byteLength(encodedParams) + header.length, 0)
+ this.socket.write(this.headerBuffer)
+ this.socket.write(encodedParams, 'utf-8')
}
- messageReceived(message:Array) {
- if (message.length === 1 || (message.length === 2 && !(typeof message[1] === 'string'))) {
- var f = this.callbacks.get(message[0])
- var singletonArray = safeGet(message, 1)
- if (singletonArray == null) {
- f()
- }
- else {
- f(singletonArray[0])
- }
- }
- else {
- var id:number
- var offset:number
- if (typeof message[0] === 'string') {
- id = -1
- offset = 0
- }
- else {
- id = message[0]
- offset = 1
- }
-
- var args = safeGet(message, offset + 2)
- var errorCallback:(message:String)=>void
- if (id === -1) {
- errorCallback = null
- }
- else {
- var resultCallback = (result:any) => this.socket.send("[" + id + ", \"r\", " + JSON.stringify(result) + "]")
- errorCallback = (error:any) => this.socket.send("[$id, \"e\", " + JSON.stringify(error) + "]")
- if (args == null) {
- args = [resultCallback, errorCallback]
- }
- else {
- var regularArgs = args
- args = regularArgs.concat(errorCallback, resultCallback)
- }
- }
-
- try {
- var o = this.domains.get(message[offset]);
- o[message[offset + 1]].apply(o, args);
- }
- catch (e) {
- console.error(e)
- if (errorCallback != null) {
- errorCallback(e)
- }
- }
- }
+ sendResult(id:number, result:any):void {
+ this.sendResultOrError(id, result, false)
}
-}
-function safeGet(a:Array, index:number):Array {
- return index < a.length ? a[index] : null
+ sendError(id:number, error:any):void {
+ this.sendResultOrError(id, error, true)
+ }
+
+ private sendResultOrError(id:number, result:any, isError:boolean):void {
+ var encodedResult = JSON.stringify(result)
+ var header = id + ', "' + (isError ? 'e': 'r') + '"';
+ this.headerBuffer.writeUInt32BE(Buffer.byteLength(encodedResult) + header.length, 0)
+ this.socket.write(this.headerBuffer)
+ this.socket.write(encodedResult, 'utf-8')
+ }
}
class MessageDecoder {
diff --git a/platform/built-in-server/client/node-rpc-client/src/rpc.ts b/platform/built-in-server/client/node-rpc-client/src/rpc.ts
new file mode 100644
index 000000000000..c7a54193f663
--- /dev/null
+++ b/platform/built-in-server/client/node-rpc-client/src/rpc.ts
@@ -0,0 +1,94 @@
+///
+///
+"use strict"
+
+import Promise = require("bluebird")
+
+class PromiseCallback {
+ constructor(public resolve:(value?:any) => void, public reject:(error?:any) => void) {
+ }
+}
+
+export interface Transport {
+ send(id:number, domain:string, command:string, params:any[]):void
+
+ sendResult(id:number, result:any):void
+
+ sendError(id:number, error:any):void
+}
+
+export class JsonRpc {
+ private messageIdCounter = 0
+ private callbacks:Map = new Map()
+ private domains:Map = new Map()
+
+ constructor(private transport:Transport) {
+ }
+
+ public call(domain:string, command:string, ...params: any[]):Promise {
+ return new Promise((resolve:(value:T) => void, reject:(error?:any) => void) => {
+ var id = this.messageIdCounter++;
+ this.callbacks.set(id, new PromiseCallback(resolve, reject))
+ this.transport.send(id, domain, command, params)
+ })
+ }
+
+ messageReceived(message:Array) {
+ if (message.length === 1 || (message.length === 2 && !(typeof message[1] === 'string'))) {
+ var promiseCallback = this.callbacks.get(message[0])
+ var singletonArray = safeGet(message, 1)
+ if (singletonArray == null) {
+ promiseCallback.resolve()
+ }
+ else {
+ promiseCallback.resolve(singletonArray[0])
+ }
+ }
+ else {
+ var id:number
+ var offset:number
+ if (typeof message[0] === 'string') {
+ id = -1
+ offset = 0
+ }
+ else {
+ id = message[0]
+ offset = 1
+ }
+
+ var onRejected = id === -1 ? null : (error:any) => this.transport.sendError(id, error)
+ try {
+ var object = this.domains.get(message[offset])
+ var method = object[message[offset + 1]]
+ var result:any
+ var args = safeGet(message, offset + 2)
+ if (args === null) {
+ result = method.call(object)
+ }
+ else {
+ result = method.apply(object, args)
+ }
+
+ if (id !== -1) {
+ var onFulfilled = (result:any) => this.transport.sendResult(id, result)
+ if (result instanceof Promise) {
+ (>result).done(onFulfilled, onRejected)
+ }
+ else {
+ onFulfilled(result)
+ }
+ }
+ }
+ catch (e) {
+ console.error(e)
+ if (onRejected != null) {
+ onRejected(e)
+ }
+ }
+ }
+ }
+}
+
+function safeGet(a:any[], index:number):Array {
+ return index < a.length ? a[index] : null
+}
\ No newline at end of file
diff --git a/platform/built-in-server/client/node-rpc-client/tsd.json b/platform/built-in-server/client/node-rpc-client/tsd.json
index af901620cee0..c5e6b3b94da0 100644
--- a/platform/built-in-server/client/node-rpc-client/tsd.json
+++ b/platform/built-in-server/client/node-rpc-client/tsd.json
@@ -7,6 +7,9 @@
"installed": {
"node/node.d.ts": {
"commit": "35fffaa44bff5392741b3022d805fe3563023a3d"
+ },
+ "bluebird/bluebird.d.ts": {
+ "commit": "cf7c97b2a68a385c98c75fb6edd81083c97c983c"
}
}
}
diff --git a/platform/built-in-server/client/node-rpc-client/typings/bluebird/bluebird.d.ts b/platform/built-in-server/client/node-rpc-client/typings/bluebird/bluebird.d.ts
new file mode 100644
index 000000000000..93c81138a8ef
--- /dev/null
+++ b/platform/built-in-server/client/node-rpc-client/typings/bluebird/bluebird.d.ts
@@ -0,0 +1,710 @@
+// Type definitions for bluebird 2.0.0
+// Project: https://github.com/petkaantonov/bluebird
+// Definitions by: Bart van der Schoor
+// Definitions: https://github.com/borisyankov/DefinitelyTyped
+
+// ES6 model with generics overload was sourced and trans-multiplied from es6-promises.d.ts
+// By: Campredon
+
+// Warning: recommended to use `tsc > v0.9.7` (critical bugs in earlier generic code):
+// - https://github.com/borisyankov/DefinitelyTyped/issues/1563
+
+// Note: replicate changes to all overloads in both definition and test file
+// Note: keep both static and instance members inline (so similar)
+
+// TODO fix remaining TODO annotations in both definition and test
+
+// TODO verify support to have no return statement in handlers to get a Promise (more overloads?)
+
+declare class Promise implements Promise.Thenable, Promise.Inspection {
+ /**
+ * Create a new promise. The passed in function will receive functions `resolve` and `reject` as its arguments which can be called to seal the fate of the created promise.
+ */
+ constructor(callback: (resolve: (thenable: Promise.Thenable) => void, reject: (error: any) => void) => void);
+ constructor(callback: (resolve: (result: R) => void, reject: (error: any) => void) => void);
+
+ /**
+ * Promises/A+ `.then()` with progress handler. Returns a new promise chained from this promise. The new promise will be rejected or resolved dedefer on the passed `fulfilledHandler`, `rejectedHandler` and the state of this promise.
+ */
+ then(onFulfill: (value: R) => Promise.Thenable, onReject: (error: any) => Promise.Thenable, onProgress?: (note: any) => any): Promise;
+ then(onFulfill: (value: R) => Promise.Thenable, onReject?: (error: any) => U, onProgress?: (note: any) => any): Promise;
+ then(onFulfill: (value: R) => U, onReject: (error: any) => Promise.Thenable, onProgress?: (note: any) => any): Promise;
+ then(onFulfill?: (value: R) => U, onReject?: (error: any) => U, onProgress?: (note: any) => any): Promise;
+
+ /**
+ * This is a catch-all exception handler, shortcut for calling `.then(null, handler)` on this promise. Any exception happening in a `.then`-chain will propagate to nearest `.catch` handler.
+ *
+ * Alias `.caught();` for compatibility with earlier ECMAScript version.
+ */
+ catch(onReject?: (error: any) => Promise.Thenable): Promise;
+ caught(onReject?: (error: any) => Promise.Thenable): Promise;
+
+ catch(onReject?: (error: any) => U): Promise;
+ caught(onReject?: (error: any) => U): Promise;
+
+ /**
+ * This extends `.catch` to work more like catch-clauses in languages like Java or C#. Instead of manually checking `instanceof` or `.name === "SomeError"`, you may specify a number of error constructors which are eligible for this catch handler. The catch handler that is first met that has eligible constructors specified, is the one that will be called.
+ *
+ * This method also supports predicate-based filters. If you pass a predicate function instead of an error constructor, the predicate will receive the error as an argument. The return result of the predicate will be used determine whether the error handler should be called.
+ *
+ * Alias `.caught();` for compatibility with earlier ECMAScript version.
+ */
+ catch(predicate: (error: any) => boolean, onReject: (error: any) => Promise.Thenable): Promise;
+ caught(predicate: (error: any) => boolean, onReject: (error: any) => Promise.Thenable): Promise;
+
+ catch(predicate: (error: any) => boolean, onReject: (error: any) => U): Promise;
+ caught(predicate: (error: any) => boolean, onReject: (error: any) => U): Promise;
+
+ catch(ErrorClass: Function, onReject: (error: any) => Promise.Thenable): Promise;
+ caught(ErrorClass: Function, onReject: (error: any) => Promise.Thenable): Promise;
+
+ catch(ErrorClass: Function, onReject: (error: any) => U): Promise;
+ caught(ErrorClass: Function, onReject: (error: any) => U): Promise;
+
+ /**
+ * Like `.catch` but instead of catching all types of exceptions, it only catches those that don't originate from thrown errors but rather from explicit rejections.
+ */
+ error(onReject: (reason: any) => Promise.Thenable): Promise;
+ error(onReject: (reason: any) => U): Promise;
+
+ /**
+ * Pass a handler that will be called regardless of this promise's fate. Returns a new promise chained from this promise. There are special semantics for `.finally()` in that the final value cannot be modified from the handler.
+ *
+ * Alias `.lastly();` for compatibility with earlier ECMAScript version.
+ */
+ finally(handler: () => Promise.Thenable): Promise;
+ finally(handler: () => U): Promise;
+
+ lastly(handler: () => Promise.Thenable): Promise;
+ lastly(handler: () => U): Promise;
+
+ /**
+ * Create a promise that follows this promise, but is bound to the given `thisArg` value. A bound promise will call its handlers with the bound value set to `this`. Additionally promises derived from a bound promise will also be bound promises with the same `thisArg` binding as the original promise.
+ */
+ bind(thisArg: any): Promise;
+
+ /**
+ * Like `.then()`, but any unhandled rejection that ends up here will be thrown as an error.
+ */
+ done(onFulfilled: (value: R) => Promise.Thenable, onRejected: (error: any) => Promise.Thenable, onProgress?: (note: any) => any): void;
+ done(onFulfilled: (value: R) => Promise.Thenable, onRejected?: (error: any) => U, onProgress?: (note: any) => any): void;
+ done(onFulfilled: (value: R) => U, onRejected: (error: any) => Promise.Thenable, onProgress?: (note: any) => any): void;
+ done(onFulfilled?: (value: R) => U, onRejected?: (error: any) => U, onProgress?: (note: any) => any): void;
+
+ /**
+ * Like `.finally()`, but not called for rejections.
+ */
+ tap(onFulFill: (value: R) => Promise.Thenable): Promise;
+ tap(onFulfill: (value: R) => U): Promise;
+
+ /**
+ * Shorthand for `.then(null, null, handler);`. Attach a progress handler that will be called if this promise is progressed. Returns a new promise chained from this promise.
+ */
+ progressed(handler: (note: any) => any): Promise;
+
+ /**
+ * Same as calling `Promise.delay(this, ms)`. With the exception that if this promise is bound to a value, the returned promise is bound to that value too.
+ */
+ delay(ms: number): Promise;
+
+ /**
+ * Returns a promise that will be fulfilled with this promise's fulfillment value or rejection reason. However, if this promise is not fulfilled or rejected within `ms` milliseconds, the returned promise is rejected with a `Promise.TimeoutError` instance.
+ *
+ * You may specify a custom error message with the `message` parameter.
+ */
+ timeout(ms: number, message?: string): Promise;
+
+ /**
+ * Register a node-style callback on this promise. When this promise is is either fulfilled or rejected, the node callback will be called back with the node.js convention where error reason is the first argument and success value is the second argument. The error argument will be `null` in case of success.
+ * Returns back this promise instead of creating a new one. If the `callback` argument is not a function, this method does not do anything.
+ */
+ nodeify(callback: (err: any, value?: R) => void): Promise;
+ nodeify(...sink: any[]): void;
+
+ /**
+ * Marks this promise as cancellable. Promises by default are not cancellable after v0.11 and must be marked as such for `.cancel()` to have any effect. Marking a promise as cancellable is infectious and you don't need to remark any descendant promise.
+ */
+ cancellable(): Promise;
+
+ /**
+ * Cancel this promise. The cancellation will propagate to farthest cancellable ancestor promise which is still pending.
+ *
+ * That ancestor will then be rejected with a `CancellationError` (get a reference from `Promise.CancellationError`) object as the rejection reason.
+ *
+ * In a promise rejection handler you may check for a cancellation by seeing if the reason object has `.name === "Cancel"`.
+ *
+ * Promises are by default not cancellable. Use `.cancellable()` to mark a promise as cancellable.
+ */
+ // TODO what to do with this?
+ cancel(): Promise;
+
+ /**
+ * Like `.then()`, but cancellation of the the returned promise or any of its descendant will not propagate cancellation to this promise or this promise's ancestors.
+ */
+ fork(onFulfilled: (value: R) => Promise.Thenable, onRejected: (error: any) => Promise.Thenable, onProgress?: (note: any) => any): Promise;
+ fork(onFulfilled: (value: R) => Promise.Thenable, onRejected?: (error: any) => U, onProgress?: (note: any) => any): Promise;
+ fork(onFulfilled: (value: R) => U, onRejected: (error: any) => Promise.Thenable, onProgress?: (note: any) => any): Promise;
+ fork(onFulfilled?: (value: R) => U, onRejected?: (error: any) => U, onProgress?: (note: any) => any): Promise;
+
+ /**
+ * Create an uncancellable promise based on this promise.
+ */
+ uncancellable(): Promise;
+
+ /**
+ * See if this promise can be cancelled.
+ */
+ isCancellable(): boolean;
+
+ /**
+ * See if this `promise` has been fulfilled.
+ */
+ isFulfilled(): boolean;
+
+ /**
+ * See if this `promise` has been rejected.
+ */
+ isRejected(): boolean;
+
+ /**
+ * See if this `promise` is still defer.
+ */
+ isPending(): boolean;
+
+ /**
+ * See if this `promise` is resolved -> either fulfilled or rejected.
+ */
+ isResolved(): boolean;
+
+ /**
+ * Get the fulfillment value of the underlying promise. Throws if the promise isn't fulfilled yet.
+ *
+ * throws `TypeError`
+ */
+ value(): R;
+
+ /**
+ * Get the rejection reason for the underlying promise. Throws if the promise isn't rejected yet.
+ *
+ * throws `TypeError`
+ */
+ reason(): any;
+
+ /**
+ * Synchronously inspect the state of this `promise`. The `PromiseInspection` will represent the state of the promise as snapshotted at the time of calling `.inspect()`.
+ */
+ inspect(): Promise.Inspection;
+
+ /**
+ * This is a convenience method for doing:
+ *
+ *
+ * promise.then(function(obj){
+ * return obj[propertyName].call(obj, arg...);
+ * });
+ *
+ */
+ call(propertyName: string, ...args: any[]): Promise;
+
+ /**
+ * This is a convenience method for doing:
+ *
+ *
+ * promise.then(function(obj){
+ * return obj[propertyName];
+ * });
+ *
+ */
+ // TODO find way to fix get()
+ // get(propertyName: string): Promise;
+
+ /**
+ * Convenience method for:
+ *
+ *
+ * .then(function() {
+ * return value;
+ * });
+ *
+ *
+ * in the case where `value` doesn't change its value. That means `value` is bound at the time of calling `.return()`
+ *
+ * Alias `.thenReturn();` for compatibility with earlier ECMAScript version.
+ */
+ return(): Promise;
+ thenReturn(): Promise;
+ return(value: U): Promise;
+ thenReturn(value: U): Promise;
+
+ /**
+ * Convenience method for:
+ *
+ *
+ * .then(function() {
+ * throw reason;
+ * });
+ *
+ * Same limitations apply as with `.return()`.
+ *
+ * Alias `.thenThrow();` for compatibility with earlier ECMAScript version.
+ */
+ throw(reason: Error): Promise;
+ thenThrow(reason: Error): Promise;
+
+ /**
+ * Convert to String.
+ */
+ toString(): string;
+
+ /**
+ * This is implicitly called by `JSON.stringify` when serializing the object. Returns a serialized representation of the `Promise`.
+ */
+ toJSON(): Object;
+
+ /**
+ * Like calling `.then`, but the fulfillment value or rejection reason is assumed to be an array, which is flattened to the formal parameters of the handlers.
+ */
+ // TODO how to model instance.spread()? like Q?
+ spread(onFulfill: Function, onReject?: (reason: any) => Promise.Thenable): Promise;
+ spread(onFulfill: Function, onReject?: (reason: any) => U): Promise;
+ /*
+ // TODO or something like this?
+ spread(onFulfill: (...values: W[]) => Promise.Thenable, onReject?: (reason: any) => Promise.Thenable): Promise;
+ spread(onFulfill: (...values: W[]) => Promise.Thenable, onReject?: (reason: any) => U): Promise;
+ spread(onFulfill: (...values: W[]) => U, onReject?: (reason: any) => Promise.Thenable): Promise;
+ spread(onFulfill: (...values: W[]) => U, onReject?: (reason: any) => U): Promise;
+ */
+ /**
+ * Same as calling `Promise.all(thisPromise)`. With the exception that if this promise is bound to a value, the returned promise is bound to that value too.
+ */
+ // TODO type inference from array-resolving promise?
+ all(): Promise;
+
+ /**
+ * Same as calling `Promise.props(thisPromise)`. With the exception that if this promise is bound to a value, the returned promise is bound to that value too.
+ */
+ // TODO how to model instance.props()?
+ props(): Promise