Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
8585e597
Commit
8585e597
authored
Sep 19, 2014
by
obscuren
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Re-writing ethereum.js. Added future/promises support.
parent
ae1de659
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
2537 additions
and
434 deletions
+2537
-434
debugger.qml
mist/assets/debugger/debugger.qml
+425
-423
html_messaging.js
mist/assets/ext/html_messaging.js
+149
-0
pre.js
mist/assets/ext/pre.js
+4
-0
q.js
mist/assets/ext/q.js
+1909
-0
qml_messaging.js
mist/assets/ext/qml_messaging.js
+13
-0
webapp.qml
mist/assets/qml/webapp.qml
+21
-8
debugger.go
mist/debugger.go
+7
-3
ui_lib.go
mist/ui_lib.go
+9
-0
No files found.
mist/assets/debugger/debugger.qml
View file @
8585e597
...
...
@@ -19,29 +19,27 @@ ApplicationWindow {
property
alias
dataText
:
rawDataField
.
text
onClosing
:
{
//compileTimer.s
top()
dbg
.
S
top
()
}
MenuBar
{
menuBar
:
MenuBar
{
Menu
{
title
:
"Debugger
"
title
:
"Edit
"
MenuItem
{
text
:
"Run"
shortcut
:
"Ctrl+r"
onTriggered
:
debugCurrent
()
text
:
"Focus code"
shortcut
:
"Ctrl+1"
onTriggered
:
{
codeEditor
.
focus
=
true
}
MenuItem
{
text
:
"Next"
shortcut
:
"Ctrl+n"
onTriggered
:
dbg
.
next
()
}
MenuItem
{
text
:
"Continue"
shortcut
:
"Ctrl+g"
onTriggered
:
dbg
.
continue
()
text
:
"Focus data"
shortcut
:
"Ctrl+2"
onTriggered
:
{
rawDataField
.
focus
=
true
}
}
MenuItem
{
text
:
"Command"
shortcut
:
"Ctrl+l"
...
...
@@ -49,30 +47,34 @@ ApplicationWindow {
dbgCommand
.
focus
=
true
}
}
MenuItem
{
text
:
"Focus code"
shortcut
:
"Ctrl+1"
onTriggered
:
{
codeEditor
.
focus
=
true
}
}
Menu
{
title
:
"Debugger"
MenuItem
{
text
:
"Focus data"
shortcut
:
"Ctrl+2"
onTriggered
:
{
rawDataField
.
focus
=
true
text
:
"Run"
shortcut
:
"Ctrl+r"
onTriggered
:
debugCurrent
()
}
MenuItem
{
text
:
"Stop"
onTriggered
:
dbp
.
stop
()
}
/*
MenuSeparator
{}
MenuItem
{
text: "Close window"
shortcut: "Ctrl+w"
onTriggered: {
win.close()
text
:
"Next"
shortcut
:
"Ctrl+n"
onTriggered
:
dbg
.
next
()
}
MenuItem
{
text
:
"Continue"
shortcut
:
"Ctrl+g"
onTriggered
:
dbg
.
continue
()
}
*/
}
}
...
...
mist/assets/ext/html_messaging.js
0 → 100644
View file @
8585e597
// The magic return variable. The magic return variable will be set during the execution of the QML call.
(
function
(
window
)
{
function
message
(
type
,
data
)
{
document
.
title
=
JSON
.
stringify
({
type
:
type
,
data
:
data
});
return
window
.
____returnData
;
}
function
isPromise
(
o
)
{
return
typeof
o
===
"object"
&&
o
.
then
}
window
.
eth
=
{
_callbacks
:
{},
_onCallbacks
:
{},
prototype
:
Object
(),
coinbase
:
function
()
{
return
new
Promise
(
function
(
resolve
,
reject
)
{
postData
({
call
:
"getCoinBase"
},
function
(
coinbase
)
{
resolve
(
coinbase
);
});
});
},
block
:
function
(
numberOrHash
)
{
return
new
Promise
(
function
(
resolve
,
reject
)
{
var
func
;
if
(
typeof
numberOrHash
==
"string"
)
{
func
=
"getBlockByHash"
;
}
else
{
func
=
"getBlockByNumber"
;
}
postData
({
call
:
func
,
args
:
[
numberOrHash
]},
function
(
block
)
{
if
(
block
)
resolve
(
block
);
else
reject
(
"not found"
);
});
});
},
transact
:
function
(
params
)
{
if
(
params
===
undefined
)
{
params
=
{};
}
if
(
params
.
endowment
!==
undefined
)
params
.
value
=
params
.
endowment
;
if
(
params
.
code
!==
undefined
)
params
.
data
=
params
.
code
;
var
promises
=
[]
if
(
isPromise
(
params
.
to
))
{
promises
.
push
(
params
.
to
.
then
(
function
(
_to
)
{
params
.
to
=
_to
;
}));
}
if
(
isPromise
(
params
.
from
))
{
promises
.
push
(
params
.
from
.
then
(
function
(
_from
)
{
params
.
from
=
_from
;
}));
}
if
(
isPromise
(
params
.
data
))
{
promises
.
push
(
params
.
data
.
then
(
function
(
_code
)
{
params
.
data
=
_code
;
}));
}
else
{
if
(
typeof
params
.
data
===
"object"
)
{
data
=
""
;
for
(
var
i
=
0
;
i
<
params
.
data
.
length
;
i
++
)
{
data
+=
params
.
data
[
i
]
}
}
else
{
data
=
params
.
data
;
}
}
// Make sure everything is string
var
fields
=
[
"value"
,
"gas"
,
"gasPrice"
];
for
(
var
i
=
0
;
i
<
fields
.
length
;
i
++
)
{
if
(
params
[
fields
[
i
]]
===
undefined
)
{
params
[
fields
[
i
]]
=
""
;
}
params
[
fields
[
i
]]
=
params
[
fields
[
i
]].
toString
();
}
// Load promises then call the last "transact".
return
Q
.
all
(
promises
).
then
(
function
()
{
return
new
Promise
(
function
(
resolve
,
reject
)
{
postData
({
call
:
"transact"
,
args
:
params
},
function
(
data
)
{
if
(
data
[
1
])
reject
(
data
[
0
]);
else
resolve
(
data
[
0
]);
});
});
})
},
compile
:
function
(
code
)
{
return
new
Promise
(
function
(
resolve
,
reject
)
{
postData
({
call
:
"compile"
,
args
:
[
code
]},
function
(
data
)
{
if
(
data
[
1
])
reject
(
data
[
0
]);
else
resolve
(
data
[
0
]);
});
});
},
key
:
function
()
{
return
new
Promise
(
function
(
resolve
,
reject
)
{
postData
({
call
:
"getKey"
},
function
(
k
)
{
resolve
(
k
);
});
});
}
};
function
postData
(
data
,
cb
)
{
data
.
_seed
=
Math
.
floor
(
Math
.
random
()
*
1000000
)
if
(
cb
)
{
eth
.
_callbacks
[
data
.
_seed
]
=
cb
;
}
if
(
data
.
args
===
undefined
)
{
data
.
args
=
[];
}
navigator
.
qt
.
postMessage
(
JSON
.
stringify
(
data
));
}
navigator
.
qt
.
onmessage
=
function
(
ev
)
{
var
data
=
JSON
.
parse
(
ev
.
data
)
if
(
data
.
_event
!==
undefined
)
{
eth
.
trigger
(
data
.
_event
,
data
.
data
);
}
else
{
if
(
data
.
_seed
)
{
var
cb
=
eth
.
_callbacks
[
data
.
_seed
];
if
(
cb
)
{
cb
.
call
(
this
,
data
.
data
)
// Remove the "trigger" callback
delete
eth
.
_callbacks
[
ev
.
_seed
];
}
}
}
}
})(
this
);
mist/assets/ext/pre.js
View file @
8585e597
...
...
@@ -35,3 +35,7 @@ navigator.qt.onmessage = function(ev) {
}
}
}
if
(
typeof
(
Promise
)
===
"undefined"
)
{
window
.
Promise
=
Q
.
Promise
;
}
mist/assets/ext/q.js
0 → 100644
View file @
8585e597
// vim:ts=4:sts=4:sw=4:
/*!
*
* Copyright 2009-2012 Kris Kowal under the terms of the MIT
* license found at http://github.com/kriskowal/q/raw/master/LICENSE
*
* With parts by Tyler Close
* Copyright 2007-2009 Tyler Close under the terms of the MIT X license found
* at http://www.opensource.org/licenses/mit-license.html
* Forked at ref_send.js version: 2009-05-11
*
* With parts by Mark Miller
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
(
function
(
definition
)
{
// Turn off strict mode for this function so we can assign to global.Q
/* jshint strict: false */
// This file will function properly as a <script> tag, or a module
// using CommonJS and NodeJS or RequireJS module formats. In
// Common/Node/RequireJS, the module exports the Q API and when
// executed as a simple <script>, it creates a Q global instead.
// Montage Require
if
(
typeof
bootstrap
===
"function"
)
{
bootstrap
(
"promise"
,
definition
);
// CommonJS
}
else
if
(
typeof
exports
===
"object"
&&
typeof
module
===
"object"
)
{
module
.
exports
=
definition
();
// RequireJS
}
else
if
(
typeof
define
===
"function"
&&
define
.
amd
)
{
define
(
definition
);
// SES (Secure EcmaScript)
}
else
if
(
typeof
ses
!==
"undefined"
)
{
if
(
!
ses
.
ok
())
{
return
;
}
else
{
ses
.
makeQ
=
definition
;
}
// <script>
}
else
{
Q
=
definition
();
}
})(
function
()
{
"use strict"
;
var
hasStacks
=
false
;
try
{
throw
new
Error
();
}
catch
(
e
)
{
hasStacks
=
!!
e
.
stack
;
}
// All code after this point will be filtered from stack traces reported
// by Q.
var
qStartingLine
=
captureLine
();
var
qFileName
;
// shims
// used for fallback in "allResolved"
var
noop
=
function
()
{};
// Use the fastest possible means to execute a task in a future turn
// of the event loop.
var
nextTick
=
(
function
()
{
// linked list of tasks (single, with head node)
var
head
=
{
task
:
void
0
,
next
:
null
};
var
tail
=
head
;
var
flushing
=
false
;
var
requestTick
=
void
0
;
var
isNodeJS
=
false
;
function
flush
()
{
/* jshint loopfunc: true */
while
(
head
.
next
)
{
head
=
head
.
next
;
var
task
=
head
.
task
;
head
.
task
=
void
0
;
var
domain
=
head
.
domain
;
if
(
domain
)
{
head
.
domain
=
void
0
;
domain
.
enter
();
}
try
{
task
();
}
catch
(
e
)
{
if
(
isNodeJS
)
{
// In node, uncaught exceptions are considered fatal errors.
// Re-throw them synchronously to interrupt flushing!
// Ensure continuation if the uncaught exception is suppressed
// listening "uncaughtException" events (as domains does).
// Continue in next event to avoid tick recursion.
if
(
domain
)
{
domain
.
exit
();
}
setTimeout
(
flush
,
0
);
if
(
domain
)
{
domain
.
enter
();
}
throw
e
;
}
else
{
// In browsers, uncaught exceptions are not fatal.
// Re-throw them asynchronously to avoid slow-downs.
setTimeout
(
function
()
{
throw
e
;
},
0
);
}
}
if
(
domain
)
{
domain
.
exit
();
}
}
flushing
=
false
;
}
nextTick
=
function
(
task
)
{
tail
=
tail
.
next
=
{
task
:
task
,
domain
:
isNodeJS
&&
process
.
domain
,
next
:
null
};
if
(
!
flushing
)
{
flushing
=
true
;
requestTick
();
}
};
if
(
typeof
process
!==
"undefined"
&&
process
.
nextTick
)
{
// Node.js before 0.9. Note that some fake-Node environments, like the
// Mocha test runner, introduce a `process` global without a `nextTick`.
isNodeJS
=
true
;
requestTick
=
function
()
{
process
.
nextTick
(
flush
);
};
}
else
if
(
typeof
setImmediate
===
"function"
)
{
// In IE10, Node.js 0.9+, or https://github.com/NobleJS/setImmediate
if
(
typeof
window
!==
"undefined"
)
{
requestTick
=
setImmediate
.
bind
(
window
,
flush
);
}
else
{
requestTick
=
function
()
{
setImmediate
(
flush
);
};
}
}
else
if
(
typeof
MessageChannel
!==
"undefined"
)
{
// modern browsers
// http://www.nonblocking.io/2011/06/windownexttick.html
var
channel
=
new
MessageChannel
();
// At least Safari Version 6.0.5 (8536.30.1) intermittently cannot create
// working message ports the first time a page loads.
channel
.
port1
.
onmessage
=
function
()
{
requestTick
=
requestPortTick
;
channel
.
port1
.
onmessage
=
flush
;
flush
();
};
var
requestPortTick
=
function
()
{
// Opera requires us to provide a message payload, regardless of
// whether we use it.
channel
.
port2
.
postMessage
(
0
);
};
requestTick
=
function
()
{
setTimeout
(
flush
,
0
);
requestPortTick
();
};
}
else
{
// old browsers
requestTick
=
function
()
{
setTimeout
(
flush
,
0
);
};
}
return
nextTick
;
})();
// Attempt to make generics safe in the face of downstream
// modifications.
// There is no situation where this is necessary.
// If you need a security guarantee, these primordials need to be
// deeply frozen anyway, and if you don’t need a security guarantee,
// this is just plain paranoid.
// However, this **might** have the nice side-effect of reducing the size of
// the minified code by reducing x.call() to merely x()
// See Mark Miller’s explanation of what this does.
// http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming
var
call
=
Function
.
call
;
function
uncurryThis
(
f
)
{
return
function
()
{
return
call
.
apply
(
f
,
arguments
);
};
}
// This is equivalent, but slower:
// uncurryThis = Function_bind.bind(Function_bind.call);
// http://jsperf.com/uncurrythis
var
array_slice
=
uncurryThis
(
Array
.
prototype
.
slice
);
var
array_reduce
=
uncurryThis
(
Array
.
prototype
.
reduce
||
function
(
callback
,
basis
)
{
var
index
=
0
,
length
=
this
.
length
;
// concerning the initial value, if one is not provided
if
(
arguments
.
length
===
1
)
{
// seek to the first value in the array, accounting
// for the possibility that is is a sparse array
do
{
if
(
index
in
this
)
{
basis
=
this
[
index
++
];
break
;
}
if
(
++
index
>=
length
)
{
throw
new
TypeError
();
}
}
while
(
1
);
}
// reduce
for
(;
index
<
length
;
index
++
)
{
// account for the possibility that the array is sparse
if
(
index
in
this
)
{
basis
=
callback
(
basis
,
this
[
index
],
index
);
}
}
return
basis
;
}
);
var
array_indexOf
=
uncurryThis
(
Array
.
prototype
.
indexOf
||
function
(
value
)
{
// not a very good shim, but good enough for our one use of it
for
(
var
i
=
0
;
i
<
this
.
length
;
i
++
)
{
if
(
this
[
i
]
===
value
)
{
return
i
;
}
}
return
-
1
;
}
);
var
array_map
=
uncurryThis
(
Array
.
prototype
.
map
||
function
(
callback
,
thisp
)
{
var
self
=
this
;
var
collect
=
[];
array_reduce
(
self
,
function
(
undefined
,
value
,
index
)
{
collect
.
push
(
callback
.
call
(
thisp
,
value
,
index
,
self
));
},
void
0
);
return
collect
;
}
);
var
object_create
=
Object
.
create
||
function
(
prototype
)
{
function
Type
()
{
}
Type
.
prototype
=
prototype
;
return
new
Type
();
};
var
object_hasOwnProperty
=
uncurryThis
(
Object
.
prototype
.
hasOwnProperty
);
var
object_keys
=
Object
.
keys
||
function
(
object
)
{
var
keys
=
[];
for
(
var
key
in
object
)
{
if
(
object_hasOwnProperty
(
object
,
key
))
{
keys
.
push
(
key
);
}
}
return
keys
;
};
var
object_toString
=
uncurryThis
(
Object
.
prototype
.
toString
);
function
isObject
(
value
)
{
return
value
===
Object
(
value
);
}
// generator related shims
// FIXME: Remove this function once ES6 generators are in SpiderMonkey.
function
isStopIteration
(
exception
)
{
return
(
object_toString
(
exception
)
===
"[object StopIteration]"
||
exception
instanceof
QReturnValue
);
}
// FIXME: Remove this helper and Q.return once ES6 generators are in
// SpiderMonkey.
var
QReturnValue
;
if
(
typeof
ReturnValue
!==
"undefined"
)
{
QReturnValue
=
ReturnValue
;
}
else
{
QReturnValue
=
function
(
value
)
{
this
.
value
=
value
;
};
}
// long stack traces
var
STACK_JUMP_SEPARATOR
=
"From previous event:"
;
function
makeStackTraceLong
(
error
,
promise
)
{
// If possible, transform the error stack trace by removing Node and Q
// cruft, then concatenating with the stack trace of `promise`. See #57.
if
(
hasStacks
&&
promise
.
stack
&&
typeof
error
===
"object"
&&
error
!==
null
&&
error
.
stack
&&
error
.
stack
.
indexOf
(
STACK_JUMP_SEPARATOR
)
===
-
1
)
{
var
stacks
=
[];
for
(
var
p
=
promise
;
!!
p
;
p
=
p
.
source
)
{
if
(
p
.
stack
)
{
stacks
.
unshift
(
p
.
stack
);
}
}
stacks
.
unshift
(
error
.
stack
);
var
concatedStacks
=
stacks
.
join
(
"
\n
"
+
STACK_JUMP_SEPARATOR
+
"
\n
"
);
error
.
stack
=
filterStackString
(
concatedStacks
);
}
}
function
filterStackString
(
stackString
)
{
var
lines
=
stackString
.
split
(
"
\n
"
);
var
desiredLines
=
[];
for
(
var
i
=
0
;
i
<
lines
.
length
;
++
i
)
{
var
line
=
lines
[
i
];
if
(
!
isInternalFrame
(
line
)
&&
!
isNodeFrame
(
line
)
&&
line
)
{
desiredLines
.
push
(
line
);
}
}
return
desiredLines
.
join
(
"
\n
"
);
}
function
isNodeFrame
(
stackLine
)
{
return
stackLine
.
indexOf
(
"(module.js:"
)
!==
-
1
||
stackLine
.
indexOf
(
"(node.js:"
)
!==
-
1
;
}
function
getFileNameAndLineNumber
(
stackLine
)
{
// Named functions: "at functionName (filename:lineNumber:columnNumber)"
// In IE10 function name can have spaces ("Anonymous function") O_o
var
attempt1
=
/at .+
\((
.+
)
:
(\d
+
)
:
(?:\d
+
)\)
$/
.
exec
(
stackLine
);
if
(
attempt1
)
{
return
[
attempt1
[
1
],
Number
(
attempt1
[
2
])];
}
// Anonymous functions: "at filename:lineNumber:columnNumber"
var
attempt2
=
/at
([^
]
+
)
:
(\d
+
)
:
(?:\d
+
)
$/
.
exec
(
stackLine
);
if
(
attempt2
)
{
return
[
attempt2
[
1
],
Number
(
attempt2
[
2
])];
}
// Firefox style: "function@filename:lineNumber or @filename:lineNumber"
var
attempt3
=
/.*@
(
.+
)
:
(\d
+
)
$/
.
exec
(
stackLine
);
if
(
attempt3
)
{
return
[
attempt3
[
1
],
Number
(
attempt3
[
2
])];
}
}
function
isInternalFrame
(
stackLine
)
{
var
fileNameAndLineNumber
=
getFileNameAndLineNumber
(
stackLine
);
if
(
!
fileNameAndLineNumber
)
{
return
false
;
}
var
fileName
=
fileNameAndLineNumber
[
0
];
var
lineNumber
=
fileNameAndLineNumber
[
1
];
return
fileName
===
qFileName
&&
lineNumber
>=
qStartingLine
&&
lineNumber
<=
qEndingLine
;
}
// discover own file name and line number range for filtering stack
// traces
function
captureLine
()
{
if
(
!
hasStacks
)
{
return
;
}
try
{
throw
new
Error
();
}
catch
(
e
)
{
var
lines
=
e
.
stack
.
split
(
"
\n
"
);
var
firstLine
=
lines
[
0
].
indexOf
(
"@"
)
>
0
?
lines
[
1
]
:
lines
[
2
];
var
fileNameAndLineNumber
=
getFileNameAndLineNumber
(
firstLine
);
if
(
!
fileNameAndLineNumber
)
{
return
;
}
qFileName
=
fileNameAndLineNumber
[
0
];
return
fileNameAndLineNumber
[
1
];
}
}
function
deprecate
(
callback
,
name
,
alternative
)
{
return
function
()
{
if
(
typeof
console
!==
"undefined"
&&
typeof
console
.
warn
===
"function"
)
{
console
.
warn
(
name
+
" is deprecated, use "
+
alternative
+
" instead."
,
new
Error
(
""
).
stack
);
}
return
callback
.
apply
(
callback
,
arguments
);
};
}
// end of shims
// beginning of real work
/**
* Constructs a promise for an immediate reference, passes promises through, or
* coerces promises from different systems.
* @param value immediate reference or promise
*/
function
Q
(
value
)
{
// If the object is already a Promise, return it directly. This enables
// the resolve function to both be used to created references from objects,
// but to tolerably coerce non-promises to promises.
if
(
value
instanceof
Promise
)
{
return
value
;
}
// assimilate thenables
if
(
isPromiseAlike
(
value
))
{
return
coerce
(
value
);
}
else
{
return
fulfill
(
value
);
}
}
Q
.
resolve
=
Q
;
/**
* Performs a task in a future turn of the event loop.
* @param {Function} task
*/
Q
.
nextTick
=
nextTick
;
/**
* Controls whether or not long stack traces will be on
*/
Q
.
longStackSupport
=
false
;
/**
* Constructs a {promise, resolve, reject} object.
*
* `resolve` is a callback to invoke with a more resolved value for the
* promise. To fulfill the promise, invoke `resolve` with any value that is
* not a thenable. To reject the promise, invoke `resolve` with a rejected
* thenable, or invoke `reject` with the reason directly. To resolve the
* promise to another thenable, thus putting it in the same state, invoke
* `resolve` with that other thenable.
*/
Q
.
defer
=
defer
;
function
defer
()
{
// if "messages" is an "Array", that indicates that the promise has not yet
// been resolved. If it is "undefined", it has been resolved. Each
// element of the messages array is itself an array of complete arguments to
// forward to the resolved promise. We coerce the resolution value to a
// promise using the `resolve` function because it handles both fully
// non-thenable values and other thenables gracefully.
var
messages
=
[],
progressListeners
=
[],
resolvedPromise
;
var
deferred
=
object_create
(
defer
.
prototype
);
var
promise
=
object_create
(
Promise
.
prototype
);
promise
.
promiseDispatch
=
function
(
resolve
,
op
,
operands
)
{
var
args
=
array_slice
(
arguments
);
if
(
messages
)
{
messages
.
push
(
args
);
if
(
op
===
"when"
&&
operands
[
1
])
{
// progress operand
progressListeners
.
push
(
operands
[
1
]);
}
}
else
{
nextTick
(
function
()
{
resolvedPromise
.
promiseDispatch
.
apply
(
resolvedPromise
,
args
);
});
}
};
// XXX deprecated
promise
.
valueOf
=
function
()
{
if
(
messages
)
{
return
promise
;
}
var
nearerValue
=
nearer
(
resolvedPromise
);
if
(
isPromise
(
nearerValue
))
{
resolvedPromise
=
nearerValue
;
// shorten chain
}
return
nearerValue
;
};
promise
.
inspect
=
function
()
{
if
(
!
resolvedPromise
)
{
return
{
state
:
"pending"
};
}
return
resolvedPromise
.
inspect
();
};
if
(
Q
.
longStackSupport
&&
hasStacks
)
{
try
{
throw
new
Error
();
}
catch
(
e
)
{
// NOTE: don't try to use `Error.captureStackTrace` or transfer the
// accessor around; that causes memory leaks as per GH-111. Just
// reify the stack trace as a string ASAP.
//
// At the same time, cut off the first line; it's always just
// "[object Promise]\n", as per the `toString`.
promise
.
stack
=
e
.
stack
.
substring
(
e
.
stack
.
indexOf
(
"
\n
"
)
+
1
);
}
}
// NOTE: we do the checks for `resolvedPromise` in each method, instead of
// consolidating them into `become`, since otherwise we'd create new
// promises with the lines `become(whatever(value))`. See e.g. GH-252.
function
become
(
newPromise
)
{
resolvedPromise
=
newPromise
;
promise
.
source
=
newPromise
;
array_reduce
(
messages
,
function
(
undefined
,
message
)
{
nextTick
(
function
()
{
newPromise
.
promiseDispatch
.
apply
(
newPromise
,
message
);
});
},
void
0
);
messages
=
void
0
;
progressListeners
=
void
0
;
}
deferred
.
promise
=
promise
;
deferred
.
resolve
=
function
(
value
)
{
if
(
resolvedPromise
)
{
return
;
}
become
(
Q
(
value
));
};
deferred
.
fulfill
=
function
(
value
)
{
if
(
resolvedPromise
)
{
return
;
}
become
(
fulfill
(
value
));
};
deferred
.
reject
=
function
(
reason
)
{
if
(
resolvedPromise
)
{
return
;
}
become
(
reject
(
reason
));
};
deferred
.
notify
=
function
(
progress
)
{
if
(
resolvedPromise
)
{
return
;
}
array_reduce
(
progressListeners
,
function
(
undefined
,
progressListener
)
{
nextTick
(
function
()
{
progressListener
(
progress
);
});
},
void
0
);
};
return
deferred
;
}
/**
* Creates a Node-style callback that will resolve or reject the deferred
* promise.
* @returns a nodeback
*/
defer
.
prototype
.
makeNodeResolver
=
function
()
{
var
self
=
this
;
return
function
(
error
,
value
)
{
if
(
error
)
{
self
.
reject
(
error
);
}
else
if
(
arguments
.
length
>
2
)
{
self
.
resolve
(
array_slice
(
arguments
,
1
));
}
else
{
self
.
resolve
(
value
);
}
};
};
/**
* @param resolver {Function} a function that returns nothing and accepts
* the resolve, reject, and notify functions for a deferred.
* @returns a promise that may be resolved with the given resolve and reject
* functions, or rejected by a thrown exception in resolver
*/
Q
.
Promise
=
promise
;
// ES6
Q
.
promise
=
promise
;
function
promise
(
resolver
)
{
if
(
typeof
resolver
!==
"function"
)
{
throw
new
TypeError
(
"resolver must be a function."
);
}
var
deferred
=
defer
();
try
{
resolver
(
deferred
.
resolve
,
deferred
.
reject
,
deferred
.
notify
);
}
catch
(
reason
)
{
deferred
.
reject
(
reason
);
}
return
deferred
.
promise
;
}
promise
.
race
=
race
;
// ES6
promise
.
all
=
all
;
// ES6
promise
.
reject
=
reject
;
// ES6
promise
.
resolve
=
Q
;
// ES6
// XXX experimental. This method is a way to denote that a local value is
// serializable and should be immediately dispatched to a remote upon request,
// instead of passing a reference.
Q
.
passByCopy
=
function
(
object
)
{
//freeze(object);
//passByCopies.set(object, true);
return
object
;
};
Promise
.
prototype
.
passByCopy
=
function
()
{
//freeze(object);
//passByCopies.set(object, true);
return
this
;
};
/**
* If two promises eventually fulfill to the same value, promises that value,
* but otherwise rejects.
* @param x {Any*}
* @param y {Any*}
* @returns {Any*} a promise for x and y if they are the same, but a rejection
* otherwise.
*
*/
Q
.
join
=
function
(
x
,
y
)
{
return
Q
(
x
).
join
(
y
);
};
Promise
.
prototype
.
join
=
function
(
that
)
{
return
Q
([
this
,
that
]).
spread
(
function
(
x
,
y
)
{
if
(
x
===
y
)
{
// TODO: "===" should be Object.is or equiv
return
x
;
}
else
{
throw
new
Error
(
"Can't join: not the same: "
+
x
+
" "
+
y
);
}
});
};
/**
* Returns a promise for the first of an array of promises to become fulfilled.
* @param answers {Array[Any*]} promises to race
* @returns {Any*} the first promise to be fulfilled
*/
Q
.
race
=
race
;
function
race
(
answerPs
)
{
return
promise
(
function
(
resolve
,
reject
)
{
// Switch to this once we can assume at least ES5
// answerPs.forEach(function(answerP) {
// Q(answerP).then(resolve, reject);
// });
// Use this in the meantime
for
(
var
i
=
0
,
len
=
answerPs
.
length
;
i
<
len
;
i
++
)
{
Q
(
answerPs
[
i
]).
then
(
resolve
,
reject
);
}
});
}
Promise
.
prototype
.
race
=
function
()
{
return
this
.
then
(
Q
.
race
);
};
/**
* Constructs a Promise with a promise descriptor object and optional fallback
* function. The descriptor contains methods like when(rejected), get(name),
* set(name, value), post(name, args), and delete(name), which all
* return either a value, a promise for a value, or a rejection. The fallback
* accepts the operation name, a resolver, and any further arguments that would
* have been forwarded to the appropriate method above had a method been
* provided with the proper name. The API makes no guarantees about the nature
* of the returned object, apart from that it is usable whereever promises are
* bought and sold.
*/
Q
.
makePromise
=
Promise
;
function
Promise
(
descriptor
,
fallback
,
inspect
)
{
if
(
fallback
===
void
0
)
{
fallback
=
function
(
op
)
{
return
reject
(
new
Error
(
"Promise does not support operation: "
+
op
));
};
}
if
(
inspect
===
void
0
)
{
inspect
=
function
()
{
return
{
state
:
"unknown"
};
};
}
var
promise
=
object_create
(
Promise
.
prototype
);
promise
.
promiseDispatch
=
function
(
resolve
,
op
,
args
)
{
var
result
;
try
{
if
(
descriptor
[
op
])
{
result
=
descriptor
[
op
].
apply
(
promise
,
args
);
}
else
{
result
=
fallback
.
call
(
promise
,
op
,
args
);
}
}
catch
(
exception
)
{
result
=
reject
(
exception
);
}
if
(
resolve
)
{
resolve
(
result
);
}
};
promise
.
inspect
=
inspect
;
// XXX deprecated `valueOf` and `exception` support
if
(
inspect
)
{
var
inspected
=
inspect
();
if
(
inspected
.
state
===
"rejected"
)
{
promise
.
exception
=
inspected
.
reason
;
}
promise
.
valueOf
=
function
()
{
var
inspected
=
inspect
();
if
(
inspected
.
state
===
"pending"
||
inspected
.
state
===
"rejected"
)
{
return
promise
;
}
return
inspected
.
value
;
};
}
return
promise
;
}
Promise
.
prototype
.
toString
=
function
()
{
return
"[object Promise]"
;
};
Promise
.
prototype
.
then
=
function
(
fulfilled
,
rejected
,
progressed
)
{
var
self
=
this
;
var
deferred
=
defer
();
var
done
=
false
;
// ensure the untrusted promise makes at most a
// single call to one of the callbacks
function
_fulfilled
(
value
)
{
try
{
return
typeof
fulfilled
===
"function"
?
fulfilled
(
value
)
:
value
;
}
catch
(
exception
)
{
return
reject
(
exception
);
}
}
function
_rejected
(
exception
)
{
if
(
typeof
rejected
===
"function"
)
{
makeStackTraceLong
(
exception
,
self
);
try
{
return
rejected
(
exception
);
}
catch
(
newException
)
{
return
reject
(
newException
);
}
}
return
reject
(
exception
);
}
function
_progressed
(
value
)
{
return
typeof
progressed
===
"function"
?
progressed
(
value
)
:
value
;
}
nextTick
(
function
()
{
self
.
promiseDispatch
(
function
(
value
)
{
if
(
done
)
{
return
;
}
done
=
true
;
deferred
.
resolve
(
_fulfilled
(
value
));
},
"when"
,
[
function
(
exception
)
{
if
(
done
)
{
return
;
}
done
=
true
;
deferred
.
resolve
(
_rejected
(
exception
));
}]);
});
// Progress propagator need to be attached in the current tick.
self
.
promiseDispatch
(
void
0
,
"when"
,
[
void
0
,
function
(
value
)
{
var
newValue
;
var
threw
=
false
;
try
{
newValue
=
_progressed
(
value
);
}
catch
(
e
)
{
threw
=
true
;
if
(
Q
.
onerror
)
{
Q
.
onerror
(
e
);
}
else
{
throw
e
;
}
}
if
(
!
threw
)
{
deferred
.
notify
(
newValue
);
}
}]);
return
deferred
.
promise
;
};
/**
* Registers an observer on a promise.
*
* Guarantees:
*
* 1. that fulfilled and rejected will be called only once.
* 2. that either the fulfilled callback or the rejected callback will be
* called, but not both.
* 3. that fulfilled and rejected will not be called in this turn.
*
* @param value promise or immediate reference to observe
* @param fulfilled function to be called with the fulfilled value
* @param rejected function to be called with the rejection exception
* @param progressed function to be called on any progress notifications
* @return promise for the return value from the invoked callback
*/
Q
.
when
=
when
;
function
when
(
value
,
fulfilled
,
rejected
,
progressed
)
{
return
Q
(
value
).
then
(
fulfilled
,
rejected
,
progressed
);
}
Promise
.
prototype
.
thenResolve
=
function
(
value
)
{
return
this
.
then
(
function
()
{
return
value
;
});
};
Q
.
thenResolve
=
function
(
promise
,
value
)
{
return
Q
(
promise
).
thenResolve
(
value
);
};
Promise
.
prototype
.
thenReject
=
function
(
reason
)
{
return
this
.
then
(
function
()
{
throw
reason
;
});
};
Q
.
thenReject
=
function
(
promise
,
reason
)
{
return
Q
(
promise
).
thenReject
(
reason
);
};
/**
* If an object is not a promise, it is as "near" as possible.
* If a promise is rejected, it is as "near" as possible too.
* If it’s a fulfilled promise, the fulfillment value is nearer.
* If it’s a deferred promise and the deferred has been resolved, the
* resolution is "nearer".
* @param object
* @returns most resolved (nearest) form of the object
*/
// XXX should we re-do this?
Q
.
nearer
=
nearer
;
function
nearer
(
value
)
{
if
(
isPromise
(
value
))
{
var
inspected
=
value
.
inspect
();
if
(
inspected
.
state
===
"fulfilled"
)
{
return
inspected
.
value
;
}
}
return
value
;
}
/**
* @returns whether the given object is a promise.
* Otherwise it is a fulfilled value.
*/
Q
.
isPromise
=
isPromise
;
function
isPromise
(
object
)
{
return
isObject
(
object
)
&&
typeof
object
.
promiseDispatch
===
"function"
&&
typeof
object
.
inspect
===
"function"
;
}
Q
.
isPromiseAlike
=
isPromiseAlike
;
function
isPromiseAlike
(
object
)
{
return
isObject
(
object
)
&&
typeof
object
.
then
===
"function"
;
}
/**
* @returns whether the given object is a pending promise, meaning not
* fulfilled or rejected.
*/
Q
.
isPending
=
isPending
;
function
isPending
(
object
)
{
return
isPromise
(
object
)
&&
object
.
inspect
().
state
===
"pending"
;
}
Promise
.
prototype
.
isPending
=
function
()
{
return
this
.
inspect
().
state
===
"pending"
;
};
/**
* @returns whether the given object is a value or fulfilled
* promise.
*/
Q
.
isFulfilled
=
isFulfilled
;
function
isFulfilled
(
object
)
{
return
!
isPromise
(
object
)
||
object
.
inspect
().
state
===
"fulfilled"
;
}
Promise
.
prototype
.
isFulfilled
=
function
()
{
return
this
.
inspect
().
state
===
"fulfilled"
;
};
/**
* @returns whether the given object is a rejected promise.
*/
Q
.
isRejected
=
isRejected
;
function
isRejected
(
object
)
{
return
isPromise
(
object
)
&&
object
.
inspect
().
state
===
"rejected"
;
}
Promise
.
prototype
.
isRejected
=
function
()
{
return
this
.
inspect
().
state
===
"rejected"
;
};
//// BEGIN UNHANDLED REJECTION TRACKING
// This promise library consumes exceptions thrown in handlers so they can be
// handled by a subsequent promise. The exceptions get added to this array when
// they are created, and removed when they are handled. Note that in ES6 or
// shimmed environments, this would naturally be a `Set`.
var
unhandledReasons
=
[];
var
unhandledRejections
=
[];
var
trackUnhandledRejections
=
true
;
function
resetUnhandledRejections
()
{
unhandledReasons
.
length
=
0
;
unhandledRejections
.
length
=
0
;
if
(
!
trackUnhandledRejections
)
{
trackUnhandledRejections
=
true
;
}
}
function
trackRejection
(
promise
,
reason
)
{
if
(
!
trackUnhandledRejections
)
{
return
;
}
unhandledRejections
.
push
(
promise
);
if
(
reason
&&
typeof
reason
.
stack
!==
"undefined"
)
{
unhandledReasons
.
push
(
reason
.
stack
);
}
else
{
unhandledReasons
.
push
(
"(no stack) "
+
reason
);
}
}
function
untrackRejection
(
promise
)
{
if
(
!
trackUnhandledRejections
)
{
return
;
}
var
at
=
array_indexOf
(
unhandledRejections
,
promise
);
if
(
at
!==
-
1
)
{
unhandledRejections
.
splice
(
at
,
1
);
unhandledReasons
.
splice
(
at
,
1
);
}
}
Q
.
resetUnhandledRejections
=
resetUnhandledRejections
;
Q
.
getUnhandledReasons
=
function
()
{
// Make a copy so that consumers can't interfere with our internal state.
return
unhandledReasons
.
slice
();
};
Q
.
stopUnhandledRejectionTracking
=
function
()
{
resetUnhandledRejections
();
trackUnhandledRejections
=
false
;
};
resetUnhandledRejections
();
//// END UNHANDLED REJECTION TRACKING
/**
* Constructs a rejected promise.
* @param reason value describing the failure
*/
Q
.
reject
=
reject
;
function
reject
(
reason
)
{
var
rejection
=
Promise
({
"when"
:
function
(
rejected
)
{
// note that the error has been handled
if
(
rejected
)
{
untrackRejection
(
this
);
}
return
rejected
?
rejected
(
reason
)
:
this
;
}
},
function
fallback
()
{
return
this
;
},
function
inspect
()
{
return
{
state
:
"rejected"
,
reason
:
reason
};
});
// Note that the reason has not been handled.
trackRejection
(
rejection
,
reason
);
return
rejection
;
}
/**
* Constructs a fulfilled promise for an immediate reference.
* @param value immediate reference
*/
Q
.
fulfill
=
fulfill
;
function
fulfill
(
value
)
{
return
Promise
({
"when"
:
function
()
{
return
value
;
},
"get"
:
function
(
name
)
{
return
value
[
name
];
},
"set"
:
function
(
name
,
rhs
)
{
value
[
name
]
=
rhs
;
},
"delete"
:
function
(
name
)
{
delete
value
[
name
];
},
"post"
:
function
(
name
,
args
)
{
// Mark Miller proposes that post with no name should apply a
// promised function.
if
(
name
===
null
||
name
===
void
0
)
{
return
value
.
apply
(
void
0
,
args
);
}
else
{
return
value
[
name
].
apply
(
value
,
args
);
}
},
"apply"
:
function
(
thisp
,
args
)
{
return
value
.
apply
(
thisp
,
args
);
},
"keys"
:
function
()
{
return
object_keys
(
value
);
}
},
void
0
,
function
inspect
()
{
return
{
state
:
"fulfilled"
,
value
:
value
};
});
}
/**
* Converts thenables to Q promises.
* @param promise thenable promise
* @returns a Q promise
*/
function
coerce
(
promise
)
{
var
deferred
=
defer
();
nextTick
(
function
()
{
try
{
promise
.
then
(
deferred
.
resolve
,
deferred
.
reject
,
deferred
.
notify
);
}
catch
(
exception
)
{
deferred
.
reject
(
exception
);
}
});
return
deferred
.
promise
;
}
/**
* Annotates an object such that it will never be
* transferred away from this process over any promise
* communication channel.
* @param object
* @returns promise a wrapping of that object that
* additionally responds to the "isDef" message
* without a rejection.
*/
Q
.
master
=
master
;
function
master
(
object
)
{
return
Promise
({
"isDef"
:
function
()
{}
},
function
fallback
(
op
,
args
)
{
return
dispatch
(
object
,
op
,
args
);
},
function
()
{
return
Q
(
object
).
inspect
();
});
}
/**
* Spreads the values of a promised array of arguments into the
* fulfillment callback.
* @param fulfilled callback that receives variadic arguments from the
* promised array
* @param rejected callback that receives the exception if the promise
* is rejected.
* @returns a promise for the return value or thrown exception of
* either callback.
*/
Q
.
spread
=
spread
;
function
spread
(
value
,
fulfilled
,
rejected
)
{
return
Q
(
value
).
spread
(
fulfilled
,
rejected
);
}
Promise
.
prototype
.
spread
=
function
(
fulfilled
,
rejected
)
{
return
this
.
all
().
then
(
function
(
array
)
{
return
fulfilled
.
apply
(
void
0
,
array
);
},
rejected
);
};
/**
* The async function is a decorator for generator functions, turning
* them into asynchronous generators. Although generators are only part
* of the newest ECMAScript 6 drafts, this code does not cause syntax
* errors in older engines. This code should continue to work and will
* in fact improve over time as the language improves.
*
* ES6 generators are currently part of V8 version 3.19 with the
* --harmony-generators runtime flag enabled. SpiderMonkey has had them
* for longer, but under an older Python-inspired form. This function
* works on both kinds of generators.
*
* Decorates a generator function such that:
* - it may yield promises
* - execution will continue when that promise is fulfilled
* - the value of the yield expression will be the fulfilled value
* - it returns a promise for the return value (when the generator
* stops iterating)
* - the decorated function returns a promise for the return value
* of the generator or the first rejected promise among those
* yielded.
* - if an error is thrown in the generator, it propagates through
* every following yield until it is caught, or until it escapes
* the generator function altogether, and is translated into a
* rejection for the promise returned by the decorated generator.
*/
Q
.
async
=
async
;
function
async
(
makeGenerator
)
{
return
function
()
{
// when verb is "send", arg is a value
// when verb is "throw", arg is an exception
function
continuer
(
verb
,
arg
)
{
var
result
;
// Until V8 3.19 / Chromium 29 is released, SpiderMonkey is the only
// engine that has a deployed base of browsers that support generators.
// However, SM's generators use the Python-inspired semantics of
// outdated ES6 drafts. We would like to support ES6, but we'd also
// like to make it possible to use generators in deployed browsers, so
// we also support Python-style generators. At some point we can remove
// this block.
if
(
typeof
StopIteration
===
"undefined"
)
{
// ES6 Generators
try
{
result
=
generator
[
verb
](
arg
);
}
catch
(
exception
)
{
return
reject
(
exception
);
}
if
(
result
.
done
)
{
return
Q
(
result
.
value
);
}
else
{
return
when
(
result
.
value
,
callback
,
errback
);
}
}
else
{
// SpiderMonkey Generators
// FIXME: Remove this case when SM does ES6 generators.
try
{
result
=
generator
[
verb
](
arg
);
}
catch
(
exception
)
{
if
(
isStopIteration
(
exception
))
{
return
Q
(
exception
.
value
);
}
else
{
return
reject
(
exception
);
}
}
return
when
(
result
,
callback
,
errback
);
}
}
var
generator
=
makeGenerator
.
apply
(
this
,
arguments
);
var
callback
=
continuer
.
bind
(
continuer
,
"next"
);
var
errback
=
continuer
.
bind
(
continuer
,
"throw"
);
return
callback
();
};
}
/**
* The spawn function is a small wrapper around async that immediately
* calls the generator and also ends the promise chain, so that any
* unhandled errors are thrown instead of forwarded to the error
* handler. This is useful because it's extremely common to run
* generators at the top-level to work with libraries.
*/
Q
.
spawn
=
spawn
;
function
spawn
(
makeGenerator
)
{
Q
.
done
(
Q
.
async
(
makeGenerator
)());
}
// FIXME: Remove this interface once ES6 generators are in SpiderMonkey.
/**
* Throws a ReturnValue exception to stop an asynchronous generator.
*
* This interface is a stop-gap measure to support generator return
* values in older Firefox/SpiderMonkey. In browsers that support ES6
* generators like Chromium 29, just use "return" in your generator
* functions.
*
* @param value the return value for the surrounding generator
* @throws ReturnValue exception with the value.
* @example
* // ES6 style
* Q.async(function* () {
* var foo = yield getFooPromise();
* var bar = yield getBarPromise();
* return foo + bar;
* })
* // Older SpiderMonkey style
* Q.async(function () {
* var foo = yield getFooPromise();
* var bar = yield getBarPromise();
* Q.return(foo + bar);
* })
*/
Q
[
"return"
]
=
_return
;
function
_return
(
value
)
{
throw
new
QReturnValue
(
value
);
}
/**
* The promised function decorator ensures that any promise arguments
* are settled and passed as values (`this` is also settled and passed
* as a value). It will also ensure that the result of a function is
* always a promise.
*
* @example
* var add = Q.promised(function (a, b) {
* return a + b;
* });
* add(Q(a), Q(B));
*
* @param {function} callback The function to decorate
* @returns {function} a function that has been decorated.
*/
Q
.
promised
=
promised
;
function
promised
(
callback
)
{
return
function
()
{
return
spread
([
this
,
all
(
arguments
)],
function
(
self
,
args
)
{
return
callback
.
apply
(
self
,
args
);
});
};
}
/**
* sends a message to a value in a future turn
* @param object* the recipient
* @param op the name of the message operation, e.g., "when",
* @param args further arguments to be forwarded to the operation
* @returns result {Promise} a promise for the result of the operation
*/
Q
.
dispatch
=
dispatch
;
function
dispatch
(
object
,
op
,
args
)
{
return
Q
(
object
).
dispatch
(
op
,
args
);
}
Promise
.
prototype
.
dispatch
=
function
(
op
,
args
)
{
var
self
=
this
;
var
deferred
=
defer
();
nextTick
(
function
()
{
self
.
promiseDispatch
(
deferred
.
resolve
,
op
,
args
);
});
return
deferred
.
promise
;
};
/**
* Gets the value of a property in a future turn.
* @param object promise or immediate reference for target object
* @param name name of property to get
* @return promise for the property value
*/
Q
.
get
=
function
(
object
,
key
)
{
return
Q
(
object
).
dispatch
(
"get"
,
[
key
]);
};
Promise
.
prototype
.
get
=
function
(
key
)
{
return
this
.
dispatch
(
"get"
,
[
key
]);
};
/**
* Sets the value of a property in a future turn.
* @param object promise or immediate reference for object object
* @param name name of property to set
* @param value new value of property
* @return promise for the return value
*/
Q
.
set
=
function
(
object
,
key
,
value
)
{
return
Q
(
object
).
dispatch
(
"set"
,
[
key
,
value
]);
};
Promise
.
prototype
.
set
=
function
(
key
,
value
)
{
return
this
.
dispatch
(
"set"
,
[
key
,
value
]);
};
/**
* Deletes a property in a future turn.
* @param object promise or immediate reference for target object
* @param name name of property to delete
* @return promise for the return value
*/
Q
.
del
=
// XXX legacy
Q
[
"delete"
]
=
function
(
object
,
key
)
{
return
Q
(
object
).
dispatch
(
"delete"
,
[
key
]);
};
Promise
.
prototype
.
del
=
// XXX legacy
Promise
.
prototype
[
"delete"
]
=
function
(
key
)
{
return
this
.
dispatch
(
"delete"
,
[
key
]);
};
/**
* Invokes a method in a future turn.
* @param object promise or immediate reference for target object
* @param name name of method to invoke
* @param value a value to post, typically an array of
* invocation arguments for promises that
* are ultimately backed with `resolve` values,
* as opposed to those backed with URLs
* wherein the posted value can be any
* JSON serializable object.
* @return promise for the return value
*/
// bound locally because it is used by other methods
Q
.
mapply
=
// XXX As proposed by "Redsandro"
Q
.
post
=
function
(
object
,
name
,
args
)
{
return
Q
(
object
).
dispatch
(
"post"
,
[
name
,
args
]);
};
Promise
.
prototype
.
mapply
=
// XXX As proposed by "Redsandro"
Promise
.
prototype
.
post
=
function
(
name
,
args
)
{
return
this
.
dispatch
(
"post"
,
[
name
,
args
]);
};
/**
* Invokes a method in a future turn.
* @param object promise or immediate reference for target object
* @param name name of method to invoke
* @param ...args array of invocation arguments
* @return promise for the return value
*/
Q
.
send
=
// XXX Mark Miller's proposed parlance
Q
.
mcall
=
// XXX As proposed by "Redsandro"
Q
.
invoke
=
function
(
object
,
name
/*...args*/
)
{
return
Q
(
object
).
dispatch
(
"post"
,
[
name
,
array_slice
(
arguments
,
2
)]);
};
Promise
.
prototype
.
send
=
// XXX Mark Miller's proposed parlance
Promise
.
prototype
.
mcall
=
// XXX As proposed by "Redsandro"
Promise
.
prototype
.
invoke
=
function
(
name
/*...args*/
)
{
return
this
.
dispatch
(
"post"
,
[
name
,
array_slice
(
arguments
,
1
)]);
};
/**
* Applies the promised function in a future turn.
* @param object promise or immediate reference for target function
* @param args array of application arguments
*/
Q
.
fapply
=
function
(
object
,
args
)
{
return
Q
(
object
).
dispatch
(
"apply"
,
[
void
0
,
args
]);
};
Promise
.
prototype
.
fapply
=
function
(
args
)
{
return
this
.
dispatch
(
"apply"
,
[
void
0
,
args
]);
};
/**
* Calls the promised function in a future turn.
* @param object promise or immediate reference for target function
* @param ...args array of application arguments
*/
Q
[
"try"
]
=
Q
.
fcall
=
function
(
object
/* ...args*/
)
{
return
Q
(
object
).
dispatch
(
"apply"
,
[
void
0
,
array_slice
(
arguments
,
1
)]);
};
Promise
.
prototype
.
fcall
=
function
(
/*...args*/
)
{
return
this
.
dispatch
(
"apply"
,
[
void
0
,
array_slice
(
arguments
)]);
};
/**
* Binds the promised function, transforming return values into a fulfilled
* promise and thrown errors into a rejected one.
* @param object promise or immediate reference for target function
* @param ...args array of application arguments
*/
Q
.
fbind
=
function
(
object
/*...args*/
)
{
var
promise
=
Q
(
object
);
var
args
=
array_slice
(
arguments
,
1
);
return
function
fbound
()
{
return
promise
.
dispatch
(
"apply"
,
[
this
,
args
.
concat
(
array_slice
(
arguments
))
]);
};
};
Promise
.
prototype
.
fbind
=
function
(
/*...args*/
)
{
var
promise
=
this
;
var
args
=
array_slice
(
arguments
);
return
function
fbound
()
{
return
promise
.
dispatch
(
"apply"
,
[
this
,
args
.
concat
(
array_slice
(
arguments
))
]);
};
};
/**
* Requests the names of the owned properties of a promised
* object in a future turn.
* @param object promise or immediate reference for target object
* @return promise for the keys of the eventually settled object
*/
Q
.
keys
=
function
(
object
)
{
return
Q
(
object
).
dispatch
(
"keys"
,
[]);
};
Promise
.
prototype
.
keys
=
function
()
{
return
this
.
dispatch
(
"keys"
,
[]);
};
/**
* Turns an array of promises into a promise for an array. If any of
* the promises gets rejected, the whole array is rejected immediately.
* @param {Array*} an array (or promise for an array) of values (or
* promises for values)
* @returns a promise for an array of the corresponding values
*/
// By Mark Miller
// http://wiki.ecmascript.org/doku.php?id=strawman:concurrency&rev=1308776521#allfulfilled
Q
.
all
=
all
;
function
all
(
promises
)
{
return
when
(
promises
,
function
(
promises
)
{
var
countDown
=
0
;
var
deferred
=
defer
();
array_reduce
(
promises
,
function
(
undefined
,
promise
,
index
)
{
var
snapshot
;
if
(
isPromise
(
promise
)
&&
(
snapshot
=
promise
.
inspect
()).
state
===
"fulfilled"
)
{
promises
[
index
]
=
snapshot
.
value
;
}
else
{
++
countDown
;
when
(
promise
,
function
(
value
)
{
promises
[
index
]
=
value
;
if
(
--
countDown
===
0
)
{
deferred
.
resolve
(
promises
);
}
},
deferred
.
reject
,
function
(
progress
)
{
deferred
.
notify
({
index
:
index
,
value
:
progress
});
}
);
}
},
void
0
);
if
(
countDown
===
0
)
{
deferred
.
resolve
(
promises
);
}
return
deferred
.
promise
;
});
}
Promise
.
prototype
.
all
=
function
()
{
return
all
(
this
);
};
/**
* Waits for all promises to be settled, either fulfilled or
* rejected. This is distinct from `all` since that would stop
* waiting at the first rejection. The promise returned by
* `allResolved` will never be rejected.
* @param promises a promise for an array (or an array) of promises
* (or values)
* @return a promise for an array of promises
*/
Q
.
allResolved
=
deprecate
(
allResolved
,
"allResolved"
,
"allSettled"
);
function
allResolved
(
promises
)
{
return
when
(
promises
,
function
(
promises
)
{
promises
=
array_map
(
promises
,
Q
);
return
when
(
all
(
array_map
(
promises
,
function
(
promise
)
{
return
when
(
promise
,
noop
,
noop
);
})),
function
()
{
return
promises
;
});
});
}
Promise
.
prototype
.
allResolved
=
function
()
{
return
allResolved
(
this
);
};
/**
* @see Promise#allSettled
*/
Q
.
allSettled
=
allSettled
;
function
allSettled
(
promises
)
{
return
Q
(
promises
).
allSettled
();
}
/**
* Turns an array of promises into a promise for an array of their states (as
* returned by `inspect`) when they have all settled.
* @param {Array[Any*]} values an array (or promise for an array) of values (or
* promises for values)
* @returns {Array[State]} an array of states for the respective values.
*/
Promise
.
prototype
.
allSettled
=
function
()
{
return
this
.
then
(
function
(
promises
)
{
return
all
(
array_map
(
promises
,
function
(
promise
)
{
promise
=
Q
(
promise
);
function
regardless
()
{
return
promise
.
inspect
();
}
return
promise
.
then
(
regardless
,
regardless
);
}));
});
};
/**
* Captures the failure of a promise, giving an oportunity to recover
* with a callback. If the given promise is fulfilled, the returned
* promise is fulfilled.
* @param {Any*} promise for something
* @param {Function} callback to fulfill the returned promise if the
* given promise is rejected
* @returns a promise for the return value of the callback
*/
Q
.
fail
=
// XXX legacy
Q
[
"catch"
]
=
function
(
object
,
rejected
)
{
return
Q
(
object
).
then
(
void
0
,
rejected
);
};
Promise
.
prototype
.
fail
=
// XXX legacy
Promise
.
prototype
[
"catch"
]
=
function
(
rejected
)
{
return
this
.
then
(
void
0
,
rejected
);
};
/**
* Attaches a listener that can respond to progress notifications from a
* promise's originating deferred. This listener receives the exact arguments
* passed to ``deferred.notify``.
* @param {Any*} promise for something
* @param {Function} callback to receive any progress notifications
* @returns the given promise, unchanged
*/
Q
.
progress
=
progress
;
function
progress
(
object
,
progressed
)
{
return
Q
(
object
).
then
(
void
0
,
void
0
,
progressed
);
}
Promise
.
prototype
.
progress
=
function
(
progressed
)
{
return
this
.
then
(
void
0
,
void
0
,
progressed
);
};
/**
* Provides an opportunity to observe the settling of a promise,
* regardless of whether the promise is fulfilled or rejected. Forwards
* the resolution to the returned promise when the callback is done.
* The callback can return a promise to defer completion.
* @param {Any*} promise
* @param {Function} callback to observe the resolution of the given
* promise, takes no arguments.
* @returns a promise for the resolution of the given promise when
* ``fin`` is done.
*/
Q
.
fin
=
// XXX legacy
Q
[
"finally"
]
=
function
(
object
,
callback
)
{
return
Q
(
object
)[
"finally"
](
callback
);
};
Promise
.
prototype
.
fin
=
// XXX legacy
Promise
.
prototype
[
"finally"
]
=
function
(
callback
)
{
callback
=
Q
(
callback
);
return
this
.
then
(
function
(
value
)
{
return
callback
.
fcall
().
then
(
function
()
{
return
value
;
});
},
function
(
reason
)
{
// TODO attempt to recycle the rejection with "this".
return
callback
.
fcall
().
then
(
function
()
{
throw
reason
;
});
});
};
/**
* Terminates a chain of promises, forcing rejections to be
* thrown as exceptions.
* @param {Any*} promise at the end of a chain of promises
* @returns nothing
*/
Q
.
done
=
function
(
object
,
fulfilled
,
rejected
,
progress
)
{
return
Q
(
object
).
done
(
fulfilled
,
rejected
,
progress
);
};
Promise
.
prototype
.
done
=
function
(
fulfilled
,
rejected
,
progress
)
{
var
onUnhandledError
=
function
(
error
)
{
// forward to a future turn so that ``when``
// does not catch it and turn it into a rejection.
nextTick
(
function
()
{
makeStackTraceLong
(
error
,
promise
);
if
(
Q
.
onerror
)
{
Q
.
onerror
(
error
);
}
else
{
throw
error
;
}
});
};
// Avoid unnecessary `nextTick`ing via an unnecessary `when`.
var
promise
=
fulfilled
||
rejected
||
progress
?
this
.
then
(
fulfilled
,
rejected
,
progress
)
:
this
;
if
(
typeof
process
===
"object"
&&
process
&&
process
.
domain
)
{
onUnhandledError
=
process
.
domain
.
bind
(
onUnhandledError
);
}
promise
.
then
(
void
0
,
onUnhandledError
);
};
/**
* Causes a promise to be rejected if it does not get fulfilled before
* some milliseconds time out.
* @param {Any*} promise
* @param {Number} milliseconds timeout
* @param {Any*} custom error message or Error object (optional)
* @returns a promise for the resolution of the given promise if it is
* fulfilled before the timeout, otherwise rejected.
*/
Q
.
timeout
=
function
(
object
,
ms
,
error
)
{
return
Q
(
object
).
timeout
(
ms
,
error
);
};
Promise
.
prototype
.
timeout
=
function
(
ms
,
error
)
{
var
deferred
=
defer
();
var
timeoutId
=
setTimeout
(
function
()
{
if
(
!
error
||
"string"
===
typeof
error
)
{
error
=
new
Error
(
error
||
"Timed out after "
+
ms
+
" ms"
);
error
.
code
=
"ETIMEDOUT"
;
}
deferred
.
reject
(
error
);
},
ms
);
this
.
then
(
function
(
value
)
{
clearTimeout
(
timeoutId
);
deferred
.
resolve
(
value
);
},
function
(
exception
)
{
clearTimeout
(
timeoutId
);
deferred
.
reject
(
exception
);
},
deferred
.
notify
);
return
deferred
.
promise
;
};
/**
* Returns a promise for the given value (or promised value), some
* milliseconds after it resolved. Passes rejections immediately.
* @param {Any*} promise
* @param {Number} milliseconds
* @returns a promise for the resolution of the given promise after milliseconds
* time has elapsed since the resolution of the given promise.
* If the given promise rejects, that is passed immediately.
*/
Q
.
delay
=
function
(
object
,
timeout
)
{
if
(
timeout
===
void
0
)
{
timeout
=
object
;
object
=
void
0
;
}
return
Q
(
object
).
delay
(
timeout
);
};
Promise
.
prototype
.
delay
=
function
(
timeout
)
{
return
this
.
then
(
function
(
value
)
{
var
deferred
=
defer
();
setTimeout
(
function
()
{
deferred
.
resolve
(
value
);
},
timeout
);
return
deferred
.
promise
;
});
};
/**
* Passes a continuation to a Node function, which is called with the given
* arguments provided as an array, and returns a promise.
*
* Q.nfapply(FS.readFile, [__filename])
* .then(function (content) {
* })
*
*/
Q
.
nfapply
=
function
(
callback
,
args
)
{
return
Q
(
callback
).
nfapply
(
args
);
};
Promise
.
prototype
.
nfapply
=
function
(
args
)
{
var
deferred
=
defer
();
var
nodeArgs
=
array_slice
(
args
);
nodeArgs
.
push
(
deferred
.
makeNodeResolver
());
this
.
fapply
(
nodeArgs
).
fail
(
deferred
.
reject
);
return
deferred
.
promise
;
};
/**
* Passes a continuation to a Node function, which is called with the given
* arguments provided individually, and returns a promise.
* @example
* Q.nfcall(FS.readFile, __filename)
* .then(function (content) {
* })
*
*/
Q
.
nfcall
=
function
(
callback
/*...args*/
)
{
var
args
=
array_slice
(
arguments
,
1
);
return
Q
(
callback
).
nfapply
(
args
);
};
Promise
.
prototype
.
nfcall
=
function
(
/*...args*/
)
{
var
nodeArgs
=
array_slice
(
arguments
);
var
deferred
=
defer
();
nodeArgs
.
push
(
deferred
.
makeNodeResolver
());
this
.
fapply
(
nodeArgs
).
fail
(
deferred
.
reject
);
return
deferred
.
promise
;
};
/**
* Wraps a NodeJS continuation passing function and returns an equivalent
* version that returns a promise.
* @example
* Q.nfbind(FS.readFile, __filename)("utf-8")
* .then(console.log)
* .done()
*/
Q
.
nfbind
=
Q
.
denodeify
=
function
(
callback
/*...args*/
)
{
var
baseArgs
=
array_slice
(
arguments
,
1
);
return
function
()
{
var
nodeArgs
=
baseArgs
.
concat
(
array_slice
(
arguments
));
var
deferred
=
defer
();
nodeArgs
.
push
(
deferred
.
makeNodeResolver
());
Q
(
callback
).
fapply
(
nodeArgs
).
fail
(
deferred
.
reject
);
return
deferred
.
promise
;
};
};
Promise
.
prototype
.
nfbind
=
Promise
.
prototype
.
denodeify
=
function
(
/*...args*/
)
{
var
args
=
array_slice
(
arguments
);
args
.
unshift
(
this
);
return
Q
.
denodeify
.
apply
(
void
0
,
args
);
};
Q
.
nbind
=
function
(
callback
,
thisp
/*...args*/
)
{
var
baseArgs
=
array_slice
(
arguments
,
2
);
return
function
()
{
var
nodeArgs
=
baseArgs
.
concat
(
array_slice
(
arguments
));
var
deferred
=
defer
();
nodeArgs
.
push
(
deferred
.
makeNodeResolver
());
function
bound
()
{
return
callback
.
apply
(
thisp
,
arguments
);
}
Q
(
bound
).
fapply
(
nodeArgs
).
fail
(
deferred
.
reject
);
return
deferred
.
promise
;
};
};
Promise
.
prototype
.
nbind
=
function
(
/*thisp, ...args*/
)
{
var
args
=
array_slice
(
arguments
,
0
);
args
.
unshift
(
this
);
return
Q
.
nbind
.
apply
(
void
0
,
args
);
};
/**
* Calls a method of a Node-style object that accepts a Node-style
* callback with a given array of arguments, plus a provided callback.
* @param object an object that has the named method
* @param {String} name name of the method of object
* @param {Array} args arguments to pass to the method; the callback
* will be provided by Q and appended to these arguments.
* @returns a promise for the value or error
*/
Q
.
nmapply
=
// XXX As proposed by "Redsandro"
Q
.
npost
=
function
(
object
,
name
,
args
)
{
return
Q
(
object
).
npost
(
name
,
args
);
};
Promise
.
prototype
.
nmapply
=
// XXX As proposed by "Redsandro"
Promise
.
prototype
.
npost
=
function
(
name
,
args
)
{
var
nodeArgs
=
array_slice
(
args
||
[]);
var
deferred
=
defer
();
nodeArgs
.
push
(
deferred
.
makeNodeResolver
());
this
.
dispatch
(
"post"
,
[
name
,
nodeArgs
]).
fail
(
deferred
.
reject
);
return
deferred
.
promise
;
};
/**
* Calls a method of a Node-style object that accepts a Node-style
* callback, forwarding the given variadic arguments, plus a provided
* callback argument.
* @param object an object that has the named method
* @param {String} name name of the method of object
* @param ...args arguments to pass to the method; the callback will
* be provided by Q and appended to these arguments.
* @returns a promise for the value or error
*/
Q
.
nsend
=
// XXX Based on Mark Miller's proposed "send"
Q
.
nmcall
=
// XXX Based on "Redsandro's" proposal
Q
.
ninvoke
=
function
(
object
,
name
/*...args*/
)
{
var
nodeArgs
=
array_slice
(
arguments
,
2
);
var
deferred
=
defer
();
nodeArgs
.
push
(
deferred
.
makeNodeResolver
());
Q
(
object
).
dispatch
(
"post"
,
[
name
,
nodeArgs
]).
fail
(
deferred
.
reject
);
return
deferred
.
promise
;
};
Promise
.
prototype
.
nsend
=
// XXX Based on Mark Miller's proposed "send"
Promise
.
prototype
.
nmcall
=
// XXX Based on "Redsandro's" proposal
Promise
.
prototype
.
ninvoke
=
function
(
name
/*...args*/
)
{
var
nodeArgs
=
array_slice
(
arguments
,
1
);
var
deferred
=
defer
();
nodeArgs
.
push
(
deferred
.
makeNodeResolver
());
this
.
dispatch
(
"post"
,
[
name
,
nodeArgs
]).
fail
(
deferred
.
reject
);
return
deferred
.
promise
;
};
/**
* If a function would like to support both Node continuation-passing-style and
* promise-returning-style, it can end its internal promise chain with
* `nodeify(nodeback)`, forwarding the optional nodeback argument. If the user
* elects to use a nodeback, the result will be sent there. If they do not
* pass a nodeback, they will receive the result promise.
* @param object a result (or a promise for a result)
* @param {Function} nodeback a Node.js-style callback
* @returns either the promise or nothing
*/
Q
.
nodeify
=
nodeify
;
function
nodeify
(
object
,
nodeback
)
{
return
Q
(
object
).
nodeify
(
nodeback
);
}
Promise
.
prototype
.
nodeify
=
function
(
nodeback
)
{
if
(
nodeback
)
{
this
.
then
(
function
(
value
)
{
nextTick
(
function
()
{
nodeback
(
null
,
value
);
});
},
function
(
error
)
{
nextTick
(
function
()
{
nodeback
(
error
);
});
});
}
else
{
return
this
;
}
};
// All code before this point will be filtered from stack traces.
var
qEndingLine
=
captureLine
();
return
Q
;
});
mist/assets/ext/qml_messaging.js
0 → 100644
View file @
8585e597
function
HandleMessage
(
data
)
{
var
message
;
try
{
message
=
JSON
.
parse
(
data
)
}
catch
(
e
)
{};
if
(
message
)
{
switch
(
message
.
type
)
{
case
"coinbase"
:
return
eth
.
coinBase
();
case
"block"
:
return
eth
.
blockByNumber
(
0
);
}
}
}
mist/assets/qml/webapp.qml
View file @
8585e597
...
...
@@ -7,6 +7,8 @@ import QtQuick.Layouts 1.0;
import
QtQuick
.
Window
2.1
;
import
Ethereum
1.0
import
"../ext/qml_messaging.js"
as
Messaging
//ApplicationWindow {
Rectangle
{
id
:
window
...
...
@@ -14,10 +16,6 @@ Rectangle {
property
var
iconSource
:
"../browser.png"
property
var
menuItem
//width: 1000
//height: 800
//minimumHeight: 300
property
alias
url
:
webview
.
url
property
alias
webView
:
webview
...
...
@@ -97,7 +95,6 @@ Rectangle {
bottom
:
parent
.
bottom
top
:
navBar
.
bottom
}
onTitleChanged
:
{
window
.
title
=
title
}
property
var
cleanPath
:
false
onNavigationRequested
:
{
...
...
@@ -113,7 +110,7 @@ Rectangle {
uri
.
replace
(
reg
,
function
(
match
,
pre
,
domain
,
path
)
{
uri
=
pre
;
var
lookup
=
ui
.
lookupDomain
(
domain
.
substring
(
0
,
domain
.
length
-
4
));
var
lookup
=
eth
.
lookupDomain
(
domain
.
substring
(
0
,
domain
.
length
-
4
));
var
ip
=
[];
for
(
var
i
=
0
,
l
=
lookup
.
length
;
i
<
l
;
i
++
)
{
ip
.
push
(
lookup
.
charCodeAt
(
i
))
...
...
@@ -138,11 +135,22 @@ Rectangle {
}
}
function
sendMessage
(
data
)
{
//this.experimental.evaluateJavaScript("window.____returnData="+JSON.stringify(data));
webview
.
experimental
.
postMessage
(
JSON
.
stringify
(
data
))
}
onTitleChanged
:
{
var
data
=
Messaging
.
HandleMessage
(
title
);
if
(
data
)
{
sendMessage
(
data
)
}
}
experimental
.
preferences
.
javascriptEnabled
:
true
experimental
.
preferences
.
navigatorQtObjectEnabled
:
true
experimental
.
preferences
.
developerExtrasEnabled
:
true
experimental.userScripts
:
[
"../ext/
pre.js"
,
"../ext/big.js"
,
"../ext/string.js"
,
"../ext/ethereum
.js"
]
experimental
.
userScripts
:
[
"../ext/
q.js"
,
"../ext/pre.js"
,
"../ext/big.js"
,
"../ext/string.js"
,
"../ext/html_messaging
.js"
]
experimental
.
onMessageReceived
:
{
console
.
log
(
"[onMessageReceived]: "
,
message
.
data
)
// TODO move to messaging.js
...
...
@@ -150,6 +158,10 @@ Rectangle {
try
{
switch
(
data
.
call
)
{
case
"compile"
:
postData
(
data
.
_seed
,
eth
.
compile
(
data
.
args
[
0
]))
break
case
"getCoinBase"
:
postData
(
data
.
_seed
,
eth
.
coinBase
())
...
...
@@ -191,7 +203,8 @@ Rectangle {
case
"transact"
:
require
(
5
)
var
tx
=
eth
.
transact
(
data
.
args
[
0
],
data
.
args
[
1
],
data
.
args
[
2
],
data
.
args
[
3
],
data
.
args
[
4
],
data
.
args
[
5
])
var
tx
=
eth
.
transact
(
data
.
args
)
console
.
log
(
"transactx"
,
tx
)
postData
(
data
.
_seed
,
tx
)
break
...
...
mist/debugger.go
View file @
8585e597
...
...
@@ -94,9 +94,7 @@ func (self *DebuggerWindow) ClearLog() {
}
func
(
self
*
DebuggerWindow
)
Debug
(
valueStr
,
gasStr
,
gasPriceStr
,
scriptStr
,
dataStr
string
)
{
if
!
self
.
Db
.
done
{
self
.
Db
.
Q
<-
true
}
self
.
Stop
()
defer
func
()
{
if
r
:=
recover
();
r
!=
nil
{
...
...
@@ -186,6 +184,12 @@ func (self *DebuggerWindow) Continue() {
self
.
Next
()
}
func
(
self
*
DebuggerWindow
)
Stop
()
{
if
!
self
.
Db
.
done
{
self
.
Db
.
Q
<-
true
}
}
func
(
self
*
DebuggerWindow
)
ExecCommand
(
command
string
)
{
if
len
(
command
)
>
0
{
cmd
:=
strings
.
Split
(
command
,
" "
)
...
...
mist/ui_lib.go
View file @
8585e597
...
...
@@ -248,3 +248,12 @@ func (self *UiLib) Transact(object map[string]interface{}) (*ethpipe.JSReceipt,
dataStr
,
)
}
func
(
self
*
UiLib
)
Compile
(
code
string
)
(
string
,
error
)
{
bcode
,
err
:=
ethutil
.
Compile
(
code
,
false
)
if
err
!=
nil
{
return
err
.
Error
(),
err
}
return
ethutil
.
Bytes2Hex
(
bcode
),
err
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment