Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
B
baas-ide
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
JIRA
JIRA
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
guxukai
baas-ide
Commits
2126391e
Commit
2126391e
authored
Oct 08, 2016
by
Alex Beregszaszi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Format using standard
parent
8914952e
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
31 changed files
with
741 additions
and
739 deletions
+741
-739
background.js
background.js
+4
-4
makeMockCompiler.js
ci/makeMockCompiler.js
+30
-30
app.js
src/app.js
+0
-0
compiler-worker.js
src/app/compiler-worker.js
+22
-22
compiler.js
src/app/compiler.js
+0
-0
debugger.js
src/app/debugger.js
+56
-56
editor.js
src/app/editor.js
+103
-103
example-contracts.js
src/app/example-contracts.js
+33
-33
execution-context.js
src/app/execution-context.js
+59
-59
formalVerification.js
src/app/formalVerification.js
+19
-19
gist-handler.js
src/app/gist-handler.js
+16
-16
query-params.js
src/app/query-params.js
+20
-20
renderer.js
src/app/renderer.js
+74
-74
storage.js
src/app/storage.js
+49
-49
ui-helper.js
src/app/ui-helper.js
+62
-62
utils.js
src/app/utils.js
+8
-8
index.js
src/index.js
+5
-5
eventManager.js
src/lib/eventManager.js
+16
-16
universal-dapp.js
src/universal-dapp.js
+0
-0
contracts.js
test-browser/helpers/contracts.js
+11
-11
compiler.js
test-browser/mockcompiler/compiler.js
+12
-12
requests.js
test-browser/mockcompiler/requests.js
+32
-32
ballot.js
test-browser/tests/ballot.js
+18
-15
debugger.js
test-browser/tests/debugger.js
+3
-3
new-file-test.js
test-browser/tests/new-file-test.js
+3
-3
simpleContract.js
test-browser/tests/simpleContract.js
+11
-11
smoke-test.js
test-browser/tests/smoke-test.js
+3
-3
compiler-test.js
test/compiler-test.js
+14
-14
gist-handler-test.js
test/gist-handler-test.js
+39
-40
index.js
test/index.js
+4
-4
query-params-test.js
test/query-params-test.js
+15
-15
No files found.
background.js
View file @
2126391e
/* global chrome */
'use strict'
;
'use strict'
chrome
.
browserAction
.
onClicked
.
addListener
(
function
(
tab
)
{
chrome
.
storage
.
sync
.
set
({
'chrome-app-sync'
:
true
})
;
chrome
.
storage
.
sync
.
set
({
'chrome-app-sync'
:
true
})
chrome
.
tabs
.
create
({
'url'
:
chrome
.
extension
.
getURL
(
'index.html'
)
},
function
(
tab
)
{
// tab opened
})
;
})
;
})
})
ci/makeMockCompiler.js
View file @
2126391e
var
fs
=
require
(
'fs'
)
;
var
solc
=
require
(
'solc/wrapper'
)
;
var
soljson
=
require
(
'../soljson'
)
;
var
compiler
=
solc
(
soljson
)
;
var
inputs
=
require
(
'../test-browser/mockcompiler/requests.js'
)
;
var
compilationResult
=
gatherCompilationResults
(
inputs
)
;
replaceSolCompiler
(
compilationResult
)
;
var
fs
=
require
(
'fs'
)
var
solc
=
require
(
'solc/wrapper'
)
var
soljson
=
require
(
'../soljson'
)
var
compiler
=
solc
(
soljson
)
var
inputs
=
require
(
'../test-browser/mockcompiler/requests.js'
)
var
compilationResult
=
gatherCompilationResults
(
inputs
)
replaceSolCompiler
(
compilationResult
)
function
gatherCompilationResults
(
sol
)
{
var
compilationResult
=
{}
;
var
compilationResult
=
{}
for
(
var
k
in
sol
)
{
var
item
=
sol
[
k
]
;
var
result
=
compile
(
item
,
1
)
;
compilationResult
[
result
.
key
]
=
result
;
result
=
compile
(
item
,
0
)
;
compilationResult
[
result
.
key
]
=
result
;
var
item
=
sol
[
k
]
var
result
=
compile
(
item
,
1
)
compilationResult
[
result
.
key
]
=
result
result
=
compile
(
item
,
0
)
compilationResult
[
result
.
key
]
=
result
}
return
compilationResult
;
return
compilationResult
}
function
compile
(
source
,
optimization
)
{
var
missingInputs
=
[]
;
var
missingInputs
=
[]
var
result
=
compiler
.
compile
(
source
,
optimization
,
function
(
path
)
{
missingInputs
.
push
(
path
)
;
})
;
var
key
=
optimization
.
toString
()
;
missingInputs
.
push
(
path
)
})
var
key
=
optimization
.
toString
()
for
(
var
k
in
source
.
sources
)
{
key
+=
k
+
source
.
sources
[
k
]
;
key
+=
k
+
source
.
sources
[
k
]
}
key
=
key
.
replace
(
/
(\t)
|
(\n)
|
(
)
/g
,
''
)
;
key
=
key
.
replace
(
/
(\t)
|
(\n)
|
(
)
/g
,
''
)
return
{
key
:
key
,
source
:
source
,
optimization
:
optimization
,
missingInputs
:
missingInputs
,
result
:
result
}
;
}
}
function
replaceSolCompiler
(
results
)
{
fs
.
readFile
(
'./test-browser/mockcompiler/compiler.js'
,
'utf8'
,
function
(
error
,
data
)
{
if
(
error
)
{
console
.
log
(
error
)
;
process
.
exit
(
1
)
;
return
;
console
.
log
(
error
)
process
.
exit
(
1
)
return
}
data
=
data
+
'
\
n
\
nvar mockData = '
+
JSON
.
stringify
(
results
)
+
';
\
n'
;
data
=
data
+
'
\
n
\
nvar mockData = '
+
JSON
.
stringify
(
results
)
+
';
\
n'
fs
.
writeFile
(
'./soljson.js'
,
data
,
'utf8'
,
function
(
error
)
{
if
(
error
)
{
console
.
log
(
error
)
;
process
.
exit
(
1
)
;
return
;
console
.
log
(
error
)
process
.
exit
(
1
)
return
}
})
;
})
;
})
})
}
src/app.js
View file @
2126391e
This diff is collapsed.
Click to expand it.
src/app/compiler-worker.js
View file @
2126391e
'use strict'
;
'use strict'
var
solc
=
require
(
'solc/wrapper'
)
;
var
solc
=
require
(
'solc/wrapper'
)
var
compileJSON
=
function
()
{
return
''
;
};
var
missingInputs
=
[]
;
var
compileJSON
=
function
()
{
return
''
}
var
missingInputs
=
[]
module
.
exports
=
function
(
self
)
{
self
.
addEventListener
(
'message'
,
function
(
e
)
{
var
data
=
e
.
data
;
var
data
=
e
.
data
switch
(
data
.
cmd
)
{
case
'loadVersion'
:
delete
self
.
Module
;
delete
self
.
Module
// NOTE: workaround some browsers?
self
.
Module
=
undefined
;
self
.
Module
=
undefined
compileJSON
=
null
;
compileJSON
=
null
self
.
importScripts
(
data
.
data
)
;
self
.
importScripts
(
data
.
data
)
var
compiler
=
solc
(
self
.
Module
)
;
var
compiler
=
solc
(
self
.
Module
)
compileJSON
=
function
(
input
,
optimize
)
{
try
{
return
JSON
.
stringify
(
compiler
.
compile
(
JSON
.
parse
(
input
),
optimize
,
function
(
path
)
{
missingInputs
.
push
(
path
)
;
return
{
'error'
:
'Deferred import'
}
;
}))
;
missingInputs
.
push
(
path
)
return
{
'error'
:
'Deferred import'
}
}))
}
catch
(
exception
)
{
return
JSON
.
stringify
({
error
:
'Uncaught JavaScript exception:
\
n'
+
exception
})
;
return
JSON
.
stringify
({
error
:
'Uncaught JavaScript exception:
\
n'
+
exception
})
}
}
;
}
self
.
postMessage
({
cmd
:
'versionLoaded'
,
data
:
compiler
.
version
(),
acceptsMultipleFiles
:
compiler
.
supportsMulti
})
;
break
;
})
break
case
'compile'
:
missingInputs
.
length
=
0
;
self
.
postMessage
({
cmd
:
'compiled'
,
job
:
data
.
job
,
data
:
compileJSON
(
data
.
source
,
data
.
optimize
),
missingInputs
:
missingInputs
})
;
break
;
missingInputs
.
length
=
0
self
.
postMessage
({
cmd
:
'compiled'
,
job
:
data
.
job
,
data
:
compileJSON
(
data
.
source
,
data
.
optimize
),
missingInputs
:
missingInputs
})
break
}
},
false
)
;
}
;
},
false
)
}
src/app/compiler.js
View file @
2126391e
This diff is collapsed.
Click to expand it.
src/app/debugger.js
View file @
2126391e
'use strict'
;
'use strict'
var
remix
=
require
(
'ethereum-remix'
)
;
var
utils
=
require
(
'./utils'
)
;
var
ace
=
require
(
'brace'
)
;
var
Range
=
ace
.
acequire
(
'ace/range'
).
Range
;
var
remix
=
require
(
'ethereum-remix'
)
var
utils
=
require
(
'./utils'
)
var
ace
=
require
(
'brace'
)
var
Range
=
ace
.
acequire
(
'ace/range'
).
Range
/**
* Manage remix and source highlighting
*/
function
Debugger
(
id
,
editor
,
compiler
,
executionContextEvent
,
switchToFile
)
{
this
.
el
=
document
.
querySelector
(
id
)
;
this
.
debugger
=
new
remix
.
ui
.
Debugger
()
;
this
.
sourceMappingDecoder
=
new
remix
.
util
.
SourceMappingDecoder
()
;
this
.
el
.
appendChild
(
this
.
debugger
.
render
())
;
this
.
editor
=
editor
;
this
.
switchToFile
=
switchToFile
;
this
.
compiler
=
compiler
;
this
.
cache
=
new
Cache
()
;
var
self
=
this
;
this
.
el
=
document
.
querySelector
(
id
)
this
.
debugger
=
new
remix
.
ui
.
Debugger
()
this
.
sourceMappingDecoder
=
new
remix
.
util
.
SourceMappingDecoder
()
this
.
el
.
appendChild
(
this
.
debugger
.
render
())
this
.
editor
=
editor
this
.
switchToFile
=
switchToFile
this
.
compiler
=
compiler
this
.
cache
=
new
Cache
()
var
self
=
this
executionContextEvent
.
register
(
'contextChanged'
,
this
,
function
(
context
)
{
self
.
switchProvider
(
context
)
;
})
;
self
.
switchProvider
(
context
)
})
this
.
lastCompilationResult
=
null
;
this
.
lastCompilationResult
=
null
this
.
debugger
.
register
(
'newTraceLoaded'
,
this
,
function
()
{
self
.
cache
.
clear
()
;
self
.
lastCompilationResult
=
self
.
compiler
.
lastCompilationResult
;
})
;
self
.
cache
.
clear
()
self
.
lastCompilationResult
=
self
.
compiler
.
lastCompilationResult
})
this
.
debugger
.
register
(
'traceUnloaded'
,
this
,
function
()
{
self
.
removeCurrentMarker
()
;
self
.
cache
.
clear
()
;
})
;
self
.
removeCurrentMarker
()
self
.
cache
.
clear
()
})
this
.
editor
.
onChangeSetup
(
function
()
{
if
(
arguments
.
length
>
0
)
{
// if arguments.length === 0 this is a session change, we don't want to stop debugging in that case
self
.
debugger
.
unLoad
()
;
self
.
debugger
.
unLoad
()
}
})
;
})
// register selected code item, highlight the corresponding source location
this
.
debugger
.
codeManager
.
register
(
'changed'
,
this
,
function
(
code
,
address
,
index
)
{
...
...
@@ -46,16 +46,16 @@ function Debugger (id, editor, compiler, executionContextEvent, switchToFile) {
this
.
debugger
.
sourceLocationTracker
.
getSourceLocation
(
address
,
index
,
self
.
lastCompilationResult
.
data
.
contracts
,
function
(
error
,
rawLocation
)
{
if
(
!
error
)
{
if
(
!
self
.
cache
.
lineBreakPositionsByContent
[
address
])
{
self
.
cache
.
lineBreakPositionsByContent
[
address
]
=
self
.
sourceMappingDecoder
.
getLinebreakPositions
(
self
.
editor
.
getFile
(
self
.
lastCompilationResult
.
data
.
sourceList
[
rawLocation
.
file
]))
;
self
.
cache
.
lineBreakPositionsByContent
[
address
]
=
self
.
sourceMappingDecoder
.
getLinebreakPositions
(
self
.
editor
.
getFile
(
self
.
lastCompilationResult
.
data
.
sourceList
[
rawLocation
.
file
]))
}
var
lineColumnPos
=
self
.
sourceMappingDecoder
.
convertOffsetToLineColumn
(
rawLocation
,
self
.
cache
.
lineBreakPositionsByContent
[
address
])
;
self
.
highlight
(
lineColumnPos
,
rawLocation
)
;
var
lineColumnPos
=
self
.
sourceMappingDecoder
.
convertOffsetToLineColumn
(
rawLocation
,
self
.
cache
.
lineBreakPositionsByContent
[
address
])
self
.
highlight
(
lineColumnPos
,
rawLocation
)
}
else
{
self
.
removeCurrentMarker
()
;
self
.
removeCurrentMarker
()
}
})
;
})
}
})
;
})
}
/**
...
...
@@ -64,13 +64,13 @@ function Debugger (id, editor, compiler, executionContextEvent, switchToFile) {
* @param {String} txHash - hash of the transaction
*/
Debugger
.
prototype
.
debug
=
function
(
txHash
)
{
var
self
=
this
;
var
self
=
this
this
.
debugger
.
web3
().
eth
.
getTransaction
(
txHash
,
function
(
error
,
tx
)
{
if
(
!
error
)
{
self
.
debugger
.
debug
(
tx
)
;
self
.
debugger
.
debug
(
tx
)
}
})
;
}
;
})
}
/**
* highlight the given @arg lineColumnPos
...
...
@@ -79,15 +79,15 @@ Debugger.prototype.debug = function (txHash) {
* @param {Object} rawLocation - raw position of the source code to hightlight {start, length, file, jump}
*/
Debugger
.
prototype
.
highlight
=
function
(
lineColumnPos
,
rawLocation
)
{
var
name
=
utils
.
fileNameFromKey
(
this
.
editor
.
getCacheFile
())
;
// current opened tab
var
source
=
this
.
lastCompilationResult
.
data
.
sourceList
[
rawLocation
.
file
]
;
// auto switch to that tab
this
.
removeCurrentMarker
()
;
var
name
=
utils
.
fileNameFromKey
(
this
.
editor
.
getCacheFile
())
// current opened tab
var
source
=
this
.
lastCompilationResult
.
data
.
sourceList
[
rawLocation
.
file
]
// auto switch to that tab
this
.
removeCurrentMarker
()
if
(
name
!==
source
)
{
this
.
switchToFile
(
source
)
;
// command the app to swicth to the next file
this
.
switchToFile
(
source
)
// command the app to swicth to the next file
}
this
.
currentRange
=
new
Range
(
lineColumnPos
.
start
.
line
,
lineColumnPos
.
start
.
column
,
lineColumnPos
.
end
.
line
,
lineColumnPos
.
end
.
column
)
;
this
.
currentMarker
=
this
.
editor
.
addMarker
(
this
.
currentRange
,
'highlightcode'
)
;
}
;
this
.
currentRange
=
new
Range
(
lineColumnPos
.
start
.
line
,
lineColumnPos
.
start
.
column
,
lineColumnPos
.
end
.
line
,
lineColumnPos
.
end
.
column
)
this
.
currentMarker
=
this
.
editor
.
addMarker
(
this
.
currentRange
,
'highlightcode'
)
}
/**
* add a new web3 provider to remix
...
...
@@ -96,8 +96,8 @@ Debugger.prototype.highlight = function (lineColumnPos, rawLocation) {
* @param {Object} obj - provider
*/
Debugger
.
prototype
.
addProvider
=
function
(
type
,
obj
)
{
this
.
debugger
.
addProvider
(
type
,
obj
)
;
}
;
this
.
debugger
.
addProvider
(
type
,
obj
)
}
/**
* switch the provider
...
...
@@ -105,32 +105,32 @@ Debugger.prototype.addProvider = function (type, obj) {
* @param {String} type - type/name of the provider to use
*/
Debugger
.
prototype
.
switchProvider
=
function
(
type
)
{
this
.
debugger
.
switchProvider
(
type
)
;
}
;
this
.
debugger
.
switchProvider
(
type
)
}
/**
* get the current provider
*/
Debugger
.
prototype
.
web3
=
function
(
type
)
{
return
this
.
debugger
.
web3
()
;
}
;
return
this
.
debugger
.
web3
()
}
/**
* unhighlight the current highlighted statement
*/
Debugger
.
prototype
.
removeCurrentMarker
=
function
()
{
if
(
this
.
currentMarker
)
{
this
.
editor
.
removeMarker
(
this
.
currentMarker
)
;
this
.
currentMarker
=
null
;
this
.
editor
.
removeMarker
(
this
.
currentMarker
)
this
.
currentMarker
=
null
}
}
;
}
function
Cache
()
{
this
.
contentLineBreakPosition
=
{}
;
this
.
contentLineBreakPosition
=
{}
}
Cache
.
prototype
.
clear
=
function
()
{
this
.
lineBreakPositionsByContent
=
{}
;
}
;
this
.
lineBreakPositionsByContent
=
{}
}
module
.
exports
=
Debugger
;
module
.
exports
=
Debugger
src/app/editor.js
View file @
2126391e
/* global FileReader */
'use strict'
;
'use strict'
var
utils
=
require
(
'./utils'
)
;
var
examples
=
require
(
'./example-contracts'
)
;
var
utils
=
require
(
'./utils'
)
var
examples
=
require
(
'./example-contracts'
)
var
ace
=
require
(
'brace'
)
;
require
(
'../mode-solidity.js'
)
;
var
ace
=
require
(
'brace'
)
require
(
'../mode-solidity.js'
)
function
Editor
(
loadingFromGist
,
storage
)
{
var
SOL_CACHE_UNTITLED
=
utils
.
fileKey
(
'Untitled'
)
;
var
SOL_CACHE_FILE
=
null
;
var
SOL_CACHE_UNTITLED
=
utils
.
fileKey
(
'Untitled'
)
var
SOL_CACHE_FILE
=
null
var
editor
=
ace
.
edit
(
'input'
)
;
var
sessions
=
{}
;
var
sourceAnnotations
=
[]
;
var
editor
=
ace
.
edit
(
'input'
)
var
sessions
=
{}
var
sourceAnnotations
=
[]
setupStuff
(
getFiles
())
;
setupStuff
(
getFiles
())
this
.
addMarker
=
function
(
range
,
cssClass
)
{
return
editor
.
session
.
addMarker
(
range
,
cssClass
)
;
}
;
return
editor
.
session
.
addMarker
(
range
,
cssClass
)
}
this
.
removeMarker
=
function
(
markerId
)
{
editor
.
session
.
removeMarker
(
markerId
)
;
}
;
editor
.
session
.
removeMarker
(
markerId
)
}
this
.
newFile
=
function
()
{
var
untitledCount
=
''
;
var
untitledCount
=
''
while
(
storage
.
exists
(
SOL_CACHE_UNTITLED
+
untitledCount
))
{
untitledCount
=
(
untitledCount
-
0
)
+
1
;
untitledCount
=
(
untitledCount
-
0
)
+
1
}
SOL_CACHE_FILE
=
SOL_CACHE_UNTITLED
+
untitledCount
;
this
.
setCacheFileContent
(
''
)
;
}
;
SOL_CACHE_FILE
=
SOL_CACHE_UNTITLED
+
untitledCount
this
.
setCacheFileContent
(
''
)
}
this
.
uploadFile
=
function
(
file
,
callback
)
{
var
fileReader
=
new
FileReader
()
;
var
cacheName
=
utils
.
fileKey
(
file
.
name
)
;
var
fileReader
=
new
FileReader
()
var
cacheName
=
utils
.
fileKey
(
file
.
name
)
fileReader
.
onload
=
function
(
e
)
{
storage
.
set
(
cacheName
,
e
.
target
.
result
)
;
SOL_CACHE_FILE
=
cacheName
;
callback
()
;
}
;
fileReader
.
readAsText
(
file
)
;
}
;
storage
.
set
(
cacheName
,
e
.
target
.
result
)
SOL_CACHE_FILE
=
cacheName
callback
()
}
fileReader
.
readAsText
(
file
)
}
this
.
setCacheFileContent
=
function
(
content
)
{
storage
.
set
(
SOL_CACHE_FILE
,
content
)
;
}
;
storage
.
set
(
SOL_CACHE_FILE
,
content
)
}
this
.
setCacheFile
=
function
(
cacheFile
)
{
SOL_CACHE_FILE
=
cacheFile
;
}
;
SOL_CACHE_FILE
=
cacheFile
}
this
.
getCacheFile
=
function
()
{
return
SOL_CACHE_FILE
;
}
;
return
SOL_CACHE_FILE
}
this
.
cacheFileIsPresent
=
function
()
{
return
!!
SOL_CACHE_FILE
;
}
;
return
!!
SOL_CACHE_FILE
}
this
.
setNextFile
=
function
(
fileKey
)
{
var
index
=
this
.
getFiles
().
indexOf
(
fileKey
)
;
this
.
setCacheFile
(
this
.
getFiles
()[
Math
.
max
(
0
,
index
-
1
)
])
;
}
;
var
index
=
this
.
getFiles
().
indexOf
(
fileKey
)
this
.
setCacheFile
(
this
.
getFiles
()[
Math
.
max
(
0
,
index
-
1
)
])
}
this
.
resetSession
=
function
()
{
editor
.
setSession
(
sessions
[
SOL_CACHE_FILE
])
;
editor
.
focus
()
;
}
;
editor
.
setSession
(
sessions
[
SOL_CACHE_FILE
])
editor
.
focus
()
}
this
.
removeSession
=
function
(
fileKey
)
{
delete
sessions
[
fileKey
]
;
}
;
delete
sessions
[
fileKey
]
}
this
.
renameSession
=
function
(
oldFileKey
,
newFileKey
)
{
if
(
oldFileKey
!==
newFileKey
)
{
sessions
[
newFileKey
]
=
sessions
[
oldFileKey
]
;
this
.
removeSession
(
oldFileKey
)
;
sessions
[
newFileKey
]
=
sessions
[
oldFileKey
]
this
.
removeSession
(
oldFileKey
)
}
}
;
}
this
.
hasFile
=
function
(
name
)
{
return
this
.
getFiles
().
indexOf
(
utils
.
fileKey
(
name
))
!==
-
1
;
}
;
return
this
.
getFiles
().
indexOf
(
utils
.
fileKey
(
name
))
!==
-
1
}
this
.
getFile
=
function
(
name
)
{
return
storage
.
get
(
utils
.
fileKey
(
name
))
;
}
;
return
storage
.
get
(
utils
.
fileKey
(
name
))
}
function
getFiles
()
{
var
files
=
[]
;
var
files
=
[]
storage
.
keys
().
forEach
(
function
(
f
)
{
if
(
utils
.
isCachedFile
(
f
))
{
files
.
push
(
f
)
;
if
(
!
sessions
[
f
])
sessions
[
f
]
=
newEditorSession
(
f
)
;
files
.
push
(
f
)
if
(
!
sessions
[
f
])
sessions
[
f
]
=
newEditorSession
(
f
)
}
})
;
return
files
;
})
return
files
}
this
.
getFiles
=
getFiles
;
this
.
getFiles
=
getFiles
this
.
packageFiles
=
function
()
{
var
files
=
{}
;
var
filesArr
=
this
.
getFiles
()
;
var
files
=
{}
var
filesArr
=
this
.
getFiles
()
for
(
var
f
in
filesArr
)
{
files
[
utils
.
fileNameFromKey
(
filesArr
[
f
])]
=
{
content
:
storage
.
get
(
filesArr
[
f
])
}
;
}
}
return
files
;
}
;
return
files
}
this
.
resize
=
function
()
{
editor
.
resize
()
;
var
session
=
editor
.
getSession
()
;
session
.
setUseWrapMode
(
document
.
querySelector
(
'#editorWrap'
).
checked
)
;
editor
.
resize
()
var
session
=
editor
.
getSession
()
session
.
setUseWrapMode
(
document
.
querySelector
(
'#editorWrap'
).
checked
)
if
(
session
.
getUseWrapMode
())
{
var
characterWidth
=
editor
.
renderer
.
characterWidth
;
var
contentWidth
=
editor
.
container
.
ownerDocument
.
getElementsByClassName
(
'ace_scroller'
)[
0
].
clientWidth
;
var
characterWidth
=
editor
.
renderer
.
characterWidth
var
contentWidth
=
editor
.
container
.
ownerDocument
.
getElementsByClassName
(
'ace_scroller'
)[
0
].
clientWidth
if
(
contentWidth
>
0
)
{
session
.
setWrapLimit
(
parseInt
(
contentWidth
/
characterWidth
,
10
))
;
session
.
setWrapLimit
(
parseInt
(
contentWidth
/
characterWidth
,
10
))
}
}
}
;
}
this
.
getValue
=
function
()
{
return
editor
.
getValue
()
;
}
;
return
editor
.
getValue
()
}
this
.
clearAnnotations
=
function
()
{
sourceAnnotations
=
[]
;
editor
.
getSession
().
clearAnnotations
()
;
}
;
sourceAnnotations
=
[]
editor
.
getSession
().
clearAnnotations
()
}
this
.
addAnnotation
=
function
(
annotation
)
{
sourceAnnotations
[
sourceAnnotations
.
length
]
=
annotation
;
this
.
setAnnotations
(
sourceAnnotations
)
;
}
;
sourceAnnotations
[
sourceAnnotations
.
length
]
=
annotation
this
.
setAnnotations
(
sourceAnnotations
)
}
this
.
setAnnotations
=
function
(
sourceAnnotations
)
{
editor
.
getSession
().
setAnnotations
(
sourceAnnotations
)
;
}
;
editor
.
getSession
().
setAnnotations
(
sourceAnnotations
)
}
this
.
onChangeSetup
=
function
(
onChange
)
{
editor
.
getSession
().
on
(
'change'
,
onChange
)
;
editor
.
getSession
().
on
(
'change'
,
onChange
)
editor
.
on
(
'changeSession'
,
function
()
{
editor
.
getSession
().
on
(
'change'
,
onChange
)
;
onChange
()
;
})
;
}
;
editor
.
getSession
().
on
(
'change'
,
onChange
)
onChange
()
})
}
this
.
handleErrorClick
=
function
(
errLine
,
errCol
)
{
editor
.
focus
()
;
editor
.
gotoLine
(
errLine
+
1
,
errCol
-
1
,
true
)
;
}
;
editor
.
focus
()
editor
.
gotoLine
(
errLine
+
1
,
errCol
-
1
,
true
)
}
function
newEditorSession
(
filekey
)
{
var
s
=
new
ace
.
EditSession
(
storage
.
get
(
filekey
),
'ace/mode/javascript'
)
;
s
.
setUndoManager
(
new
ace
.
UndoManager
())
;
s
.
setTabSize
(
4
)
;
s
.
setUseSoftTabs
(
true
)
;
sessions
[
filekey
]
=
s
;
return
s
;
var
s
=
new
ace
.
EditSession
(
storage
.
get
(
filekey
),
'ace/mode/javascript'
)
s
.
setUndoManager
(
new
ace
.
UndoManager
())
s
.
setTabSize
(
4
)
s
.
setUseSoftTabs
(
true
)
sessions
[
filekey
]
=
s
return
s
}
function
setupStuff
(
files
)
{
if
(
files
.
length
===
0
)
{
if
(
loadingFromGist
)
return
;
files
.
push
(
utils
.
fileKey
(
examples
.
ballot
.
name
))
;
storage
.
set
(
utils
.
fileKey
(
examples
.
ballot
.
name
),
examples
.
ballot
.
content
)
;
if
(
loadingFromGist
)
return
files
.
push
(
utils
.
fileKey
(
examples
.
ballot
.
name
))
storage
.
set
(
utils
.
fileKey
(
examples
.
ballot
.
name
),
examples
.
ballot
.
content
)
}
SOL_CACHE_FILE
=
files
[
0
]
;
SOL_CACHE_FILE
=
files
[
0
]
for
(
var
x
in
files
)
{
sessions
[
files
[
x
]]
=
newEditorSession
(
files
[
x
])
;
sessions
[
files
[
x
]]
=
newEditorSession
(
files
[
x
])
}
editor
.
setSession
(
sessions
[
SOL_CACHE_FILE
])
;
editor
.
resize
(
true
)
;
editor
.
setSession
(
sessions
[
SOL_CACHE_FILE
])
editor
.
resize
(
true
)
// Unmap ctrl-t & ctrl-f
editor
.
commands
.
bindKeys
({
'ctrl-t'
:
null
})
;
editor
.
commands
.
bindKeys
({
'ctrl-f'
:
null
})
;
editor
.
commands
.
bindKeys
({
'ctrl-t'
:
null
})
editor
.
commands
.
bindKeys
({
'ctrl-f'
:
null
})
}
}
module
.
exports
=
Editor
;
module
.
exports
=
Editor
src/app/example-contracts.js
View file @
2126391e
var
ballot
=
`pragma solidity ^0.4.0
;
var
ballot
=
`pragma solidity ^0.4.0
contract Ballot {
struct Voter {
uint weight
;
bool voted
;
uint8 vote
;
address delegate
;
uint weight
bool voted
uint8 vote
address delegate
}
struct Proposal {
uint voteCount
;
uint voteCount
}
address chairperson
;
mapping(address => Voter) voters
;
Proposal[] proposals
;
address chairperson
mapping(address => Voter) voters
Proposal[] proposals
/// Create a new ballot with $(_numProposals) different proposals.
function Ballot(uint8 _numProposals) {
chairperson = msg.sender
;
voters[chairperson].weight = 1
;
proposals.length = _numProposals
;
chairperson = msg.sender
voters[chairperson].weight = 1
proposals.length = _numProposals
}
/// Give $(voter) the right to vote on this ballot.
/// May only be called by $(chairperson).
function giveRightToVote(address voter) {
if (msg.sender != chairperson || voters[voter].voted) return
;
voters[voter].weight = 1
;
if (msg.sender != chairperson || voters[voter].voted) return
voters[voter].weight = 1
}
/// Delegate your vote to the voter $(to).
function delegate(address to) {
Voter sender = voters[msg.sender]
;
// assigns reference
if (sender.voted) return
;
Voter sender = voters[msg.sender] // assigns reference
if (sender.voted) return
while (voters[to].delegate != address(0) && voters[to].delegate != msg.sender)
to = voters[to].delegate
;
if (to == msg.sender) return
;
sender.voted = true
;
sender.delegate = to
;
Voter delegate = voters[to]
;
to = voters[to].delegate
if (to == msg.sender) return
sender.voted = true
sender.delegate = to
Voter delegate = voters[to]
if (delegate.voted)
proposals[delegate.vote].voteCount += sender.weight
;
proposals[delegate.vote].voteCount += sender.weight
else
delegate.weight += sender.weight
;
delegate.weight += sender.weight
}
/// Give a single vote to proposal $(proposal).
function vote(uint8 proposal) {
Voter sender = voters[msg.sender]
;
if (sender.voted || proposal >= proposals.length) return
;
sender.voted = true
;
sender.vote = proposal
;
proposals[proposal].voteCount += sender.weight
;
Voter sender = voters[msg.sender]
if (sender.voted || proposal >= proposals.length) return
sender.voted = true
sender.vote = proposal
proposals[proposal].voteCount += sender.weight
}
function winningProposal() constant returns (uint8 winningProposal) {
uint256 winningVoteCount = 0
;
uint256 winningVoteCount = 0
for (uint8 proposal = 0; proposal < proposals.length; proposal++)
if (proposals[proposal].voteCount > winningVoteCount) {
winningVoteCount = proposals[proposal].voteCount
;
winningProposal = proposal
;
winningVoteCount = proposals[proposal].voteCount
winningProposal = proposal
}
}
}`
;
}`
module
.
exports
=
{
ballot
:
{
name
:
'ballot.sol'
,
content
:
ballot
}
}
;
}
src/app/execution-context.js
View file @
2126391e
/* global confirm */
'use strict'
;
'use strict'
var
$
=
require
(
'jquery'
)
;
var
Web3
=
require
(
'web3'
)
;
var
EventManager
=
require
(
'../lib/eventManager'
)
;
var
EthJSVM
=
require
(
'ethereumjs-vm'
)
;
var
$
=
require
(
'jquery'
)
var
Web3
=
require
(
'web3'
)
var
EventManager
=
require
(
'../lib/eventManager'
)
var
EthJSVM
=
require
(
'ethereumjs-vm'
)
var
injectedProvider
;
var
injectedProvider
var
web3
;
var
web3
if
(
typeof
window
.
web3
!==
'undefined'
)
{
injectedProvider
=
window
.
web3
.
currentProvider
;
web3
=
new
Web3
(
injectedProvider
)
;
injectedProvider
=
window
.
web3
.
currentProvider
web3
=
new
Web3
(
injectedProvider
)
}
else
{
web3
=
new
Web3
(
new
Web3
.
providers
.
HttpProvider
(
'http://localhost:8545'
))
;
web3
=
new
Web3
(
new
Web3
.
providers
.
HttpProvider
(
'http://localhost:8545'
))
}
var
vm
=
new
EthJSVM
(
null
,
null
,
{
activatePrecompiles
:
true
,
enableHomestead
:
true
})
;
vm
.
stateManager
.
checkpoint
()
;
var
vm
=
new
EthJSVM
(
null
,
null
,
{
activatePrecompiles
:
true
,
enableHomestead
:
true
})
vm
.
stateManager
.
checkpoint
()
/*
trigger contextChanged, web3EndpointChanged
*/
function
ExecutionContext
()
{
var
self
=
this
;
this
.
event
=
new
EventManager
()
;
var
executionContext
=
injectedProvider
?
'injected'
:
'vm'
;
var
self
=
this
this
.
event
=
new
EventManager
()
var
executionContext
=
injectedProvider
?
'injected'
:
'vm'
this
.
isVM
=
function
()
{
return
executionContext
===
'vm'
;
}
;
return
executionContext
===
'vm'
}
this
.
web3
=
function
()
{
return
web3
;
}
;
return
web3
}
this
.
vm
=
function
()
{
return
vm
;
}
;
return
vm
}
this
.
setEndPointUrl
=
function
(
url
)
{
$web3endpoint
.
val
(
url
)
;
}
;
$web3endpoint
.
val
(
url
)
}
this
.
setContext
=
function
(
context
)
{
executionContext
=
context
;
executionContextChange
(
context
)
;
setExecutionContextRadio
()
;
}
;
executionContext
=
context
executionContextChange
(
context
)
setExecutionContextRadio
()
}
var
$injectedToggle
=
$
(
'#injected-mode'
)
;
var
$vmToggle
=
$
(
'#vm-mode'
)
;
var
$web3Toggle
=
$
(
'#web3-mode'
)
;
var
$web3endpoint
=
$
(
'#web3Endpoint'
)
;
var
$injectedToggle
=
$
(
'#injected-mode'
)
var
$vmToggle
=
$
(
'#vm-mode'
)
var
$web3Toggle
=
$
(
'#web3-mode'
)
var
$web3endpoint
=
$
(
'#web3Endpoint'
)
if
(
web3
.
providers
&&
web3
.
currentProvider
instanceof
web3
.
providers
.
IpcProvider
)
{
$web3endpoint
.
val
(
'ipc'
)
;
$web3endpoint
.
val
(
'ipc'
)
}
setExecutionContextRadio
()
;
setExecutionContextRadio
()
$injectedToggle
.
on
(
'change'
,
executionContextUIChange
)
;
$vmToggle
.
on
(
'change'
,
executionContextUIChange
)
;
$web3Toggle
.
on
(
'change'
,
executionContextUIChange
)
;
$injectedToggle
.
on
(
'change'
,
executionContextUIChange
)
$vmToggle
.
on
(
'change'
,
executionContextUIChange
)
$web3Toggle
.
on
(
'change'
,
executionContextUIChange
)
$web3endpoint
.
on
(
'change'
,
function
()
{
setProviderFromEndpoint
()
;
setProviderFromEndpoint
()
if
(
executionContext
===
'web3'
)
{
self
.
event
.
trigger
(
'web3EndpointChanged'
)
;
self
.
event
.
trigger
(
'web3EndpointChanged'
)
}
})
;
})
function
executionContextUIChange
(
ev
)
{
executionContextChange
(
ev
.
target
.
value
)
;
executionContextChange
(
ev
.
target
.
value
)
}
function
executionContextChange
(
context
)
{
if
(
context
===
'web3'
&&
!
confirm
(
'Are you sure you want to connect to a local ethereum node?'
))
{
setExecutionContextRadio
()
;
setExecutionContextRadio
()
}
else
if
(
context
===
'injected'
&&
injectedProvider
===
undefined
)
{
setExecutionContextRadio
()
;
setExecutionContextRadio
()
}
else
{
if
(
context
===
'web3'
)
{
executionContext
=
context
;
setProviderFromEndpoint
()
;
self
.
event
.
trigger
(
'contextChanged'
,
[
'web3'
])
;
executionContext
=
context
setProviderFromEndpoint
()
self
.
event
.
trigger
(
'contextChanged'
,
[
'web3'
])
}
else
if
(
context
===
'injected'
)
{
executionContext
=
context
;
web3
.
setProvider
(
injectedProvider
)
;
self
.
event
.
trigger
(
'contextChanged'
,
[
'injected'
])
;
executionContext
=
context
web3
.
setProvider
(
injectedProvider
)
self
.
event
.
trigger
(
'contextChanged'
,
[
'injected'
])
}
else
if
(
context
===
'vm'
)
{
executionContext
=
context
;
executionContext
=
context
vm
.
stateManager
.
revert
(
function
()
{
vm
.
stateManager
.
checkpoint
()
;
})
;
self
.
event
.
trigger
(
'contextChanged'
,
[
'vm'
])
;
vm
.
stateManager
.
checkpoint
()
})
self
.
event
.
trigger
(
'contextChanged'
,
[
'vm'
])
}
}
}
function
setProviderFromEndpoint
()
{
var
endpoint
=
$web3endpoint
.
val
()
;
var
endpoint
=
$web3endpoint
.
val
()
if
(
endpoint
===
'ipc'
)
{
web3
.
setProvider
(
new
web3
.
providers
.
IpcProvider
())
;
web3
.
setProvider
(
new
web3
.
providers
.
IpcProvider
())
}
else
{
web3
.
setProvider
(
new
web3
.
providers
.
HttpProvider
(
endpoint
))
;
web3
.
setProvider
(
new
web3
.
providers
.
HttpProvider
(
endpoint
))
}
}
function
setExecutionContextRadio
()
{
if
(
executionContext
===
'injected'
)
{
$injectedToggle
.
get
(
0
).
checked
=
true
;
$injectedToggle
.
get
(
0
).
checked
=
true
}
else
if
(
executionContext
===
'vm'
)
{
$vmToggle
.
get
(
0
).
checked
=
true
;
$vmToggle
.
get
(
0
).
checked
=
true
}
else
if
(
executionContext
===
'web3'
)
{
$web3Toggle
.
get
(
0
).
checked
=
true
;
$web3Toggle
.
get
(
0
).
checked
=
true
}
}
}
module
.
exports
=
ExecutionContext
;
module
.
exports
=
ExecutionContext
src/app/formalVerification.js
View file @
2126391e
'use strict'
;
'use strict'
var
$
=
require
(
'jquery'
)
;
var
EventManager
=
require
(
'../lib/eventManager'
)
;
var
$
=
require
(
'jquery'
)
var
EventManager
=
require
(
'../lib/eventManager'
)
/*
trigger compilationFinished
*/
function
FormalVerification
(
outputElement
,
compilerEvent
)
{
this
.
event
=
new
EventManager
()
;
this
.
outputElement
=
outputElement
;
var
self
=
this
;
this
.
event
=
new
EventManager
()
this
.
outputElement
=
outputElement
var
self
=
this
compilerEvent
.
register
(
'compilationFinished'
,
this
,
function
(
success
,
data
,
source
)
{
if
(
success
)
{
self
.
compilationFinished
(
data
)
;
self
.
compilationFinished
(
data
)
}
})
;
})
compilerEvent
.
register
(
'compilationStarted'
,
this
,
function
()
{
$
(
'#formalVerificationInput'
,
self
.
outputElement
)
.
val
(
''
)
.
hide
();
$
(
'#formalVerificationErrors'
).
empty
()
;
})
;
.
val
(
''
)
.
hide
()
$
(
'#formalVerificationErrors'
).
empty
()
})
}
FormalVerification
.
prototype
.
compilationFinished
=
function
(
compilationResult
)
{
if
(
compilationResult
.
formal
===
undefined
)
{
this
.
event
.
trigger
(
'compilationFinished'
,
[
false
,
'Formal verification not supported by this compiler version.'
,
$
(
'#formalVerificationErrors'
),
true
])
;
this
.
event
.
trigger
(
'compilationFinished'
,
[
false
,
'Formal verification not supported by this compiler version.'
,
$
(
'#formalVerificationErrors'
),
true
])
}
else
{
if
(
compilationResult
.
formal
[
'why3'
]
!==
undefined
)
{
$
(
'#formalVerificationInput'
,
this
.
outputElement
).
val
(
'(* copy this to http://why3.lri.fr/try/ *)'
+
compilationResult
.
formal
[
'why3'
]
)
.
show
()
;
.
show
()
}
if
(
compilationResult
.
formal
.
errors
!==
undefined
)
{
var
errors
=
compilationResult
.
formal
.
errors
;
var
errors
=
compilationResult
.
formal
.
errors
for
(
var
i
=
0
;
i
<
errors
.
length
;
i
++
)
{
this
.
event
.
trigger
(
'compilationFinished'
,
[
false
,
errors
[
i
],
$
(
'#formalVerificationErrors'
),
true
])
;
this
.
event
.
trigger
(
'compilationFinished'
,
[
false
,
errors
[
i
],
$
(
'#formalVerificationErrors'
),
true
])
}
}
else
{
this
.
event
.
trigger
(
'compilationFinished'
,
[
true
,
null
,
null
,
true
])
;
this
.
event
.
trigger
(
'compilationFinished'
,
[
true
,
null
,
null
,
true
])
}
}
}
;
}
module
.
exports
=
FormalVerification
;
module
.
exports
=
FormalVerification
src/app/gist-handler.js
View file @
2126391e
'use strict'
;
'use strict'
// Allowing window to be overriden for testing
function
GistHandler
(
_window
)
{
if
(
_window
===
undefined
)
_window
=
window
;
if
(
_window
===
undefined
)
_window
=
window
this
.
handleLoad
=
function
(
params
,
cb
)
{
var
loadingFromGist
=
false
;
var
gistId
;
var
loadingFromGist
=
false
var
gistId
if
(
params
[
'gist'
]
===
''
)
{
var
str
=
_window
.
prompt
(
'Enter the URL or ID of the Gist you would like to load.'
)
;
var
str
=
_window
.
prompt
(
'Enter the URL or ID of the Gist you would like to load.'
)
if
(
str
!==
''
)
{
gistId
=
getGistId
(
str
)
;
loadingFromGist
=
!!
gistId
;
gistId
=
getGistId
(
str
)
loadingFromGist
=
!!
gistId
}
}
else
{
gistId
=
params
[
'gist'
]
;
loadingFromGist
=
!!
gistId
;
gistId
=
params
[
'gist'
]
loadingFromGist
=
!!
gistId
}
if
(
loadingFromGist
)
{
cb
(
gistId
)
;
cb
(
gistId
)
}
return
loadingFromGist
;
}
;
return
loadingFromGist
}
function
getGistId
(
str
)
{
var
idr
=
/
[
0-9A-Fa-f
]{8,}
/
;
var
match
=
idr
.
exec
(
str
)
;
return
match
?
match
[
0
]
:
null
;
var
idr
=
/
[
0-9A-Fa-f
]{8,}
/
var
match
=
idr
.
exec
(
str
)
return
match
?
match
[
0
]
:
null
}
}
module
.
exports
=
GistHandler
;
module
.
exports
=
GistHandler
src/app/query-params.js
View file @
2126391e
'use strict'
;
'use strict'
// Allowing window to be overriden for testing
function
QueryParams
(
_window
)
{
if
(
_window
===
undefined
)
_window
=
window
;
if
(
_window
===
undefined
)
_window
=
window
this
.
get
=
function
()
{
var
qs
=
_window
.
location
.
hash
.
substr
(
1
)
;
var
qs
=
_window
.
location
.
hash
.
substr
(
1
)
if
(
_window
.
location
.
search
.
length
>
0
)
{
// use legacy query params instead of hash
_window
.
location
.
hash
=
_window
.
location
.
search
.
substr
(
1
)
;
_window
.
location
.
search
=
''
;
_window
.
location
.
hash
=
_window
.
location
.
search
.
substr
(
1
)
_window
.
location
.
search
=
''
}
var
params
=
{}
;
var
parts
=
qs
.
split
(
'&'
)
;
var
params
=
{}
var
parts
=
qs
.
split
(
'&'
)
for
(
var
x
in
parts
)
{
var
keyValue
=
parts
[
x
].
split
(
'='
)
;
var
keyValue
=
parts
[
x
].
split
(
'='
)
if
(
keyValue
[
0
]
!==
''
)
{
params
[
keyValue
[
0
]]
=
keyValue
[
1
]
;
params
[
keyValue
[
0
]]
=
keyValue
[
1
]
}
}
return
params
;
}
;
return
params
}
this
.
update
=
function
(
params
)
{
var
currentParams
=
this
.
get
()
;
var
keys
=
Object
.
keys
(
params
)
;
var
currentParams
=
this
.
get
()
var
keys
=
Object
.
keys
(
params
)
for
(
var
x
in
keys
)
{
currentParams
[
keys
[
x
]]
=
params
[
keys
[
x
]]
;
currentParams
[
keys
[
x
]]
=
params
[
keys
[
x
]]
}
var
queryString
=
'#'
;
var
updatedKeys
=
Object
.
keys
(
currentParams
)
;
var
queryString
=
'#'
var
updatedKeys
=
Object
.
keys
(
currentParams
)
for
(
var
y
in
updatedKeys
)
{
queryString
+=
updatedKeys
[
y
]
+
'='
+
currentParams
[
updatedKeys
[
y
]]
+
'&'
;
queryString
+=
updatedKeys
[
y
]
+
'='
+
currentParams
[
updatedKeys
[
y
]]
+
'&'
}
_window
.
location
.
hash
=
queryString
.
slice
(
0
,
-
1
)
;
}
;
_window
.
location
.
hash
=
queryString
.
slice
(
0
,
-
1
)
}
}
module
.
exports
=
QueryParams
;
module
.
exports
=
QueryParams
src/app/renderer.js
View file @
2126391e
'use strict'
;
'use strict'
var
$
=
require
(
'jquery'
)
;
var
$
=
require
(
'jquery'
)
var
utils
=
require
(
'./utils'
)
;
var
uiHelper
=
require
(
'./ui-helper'
)
;
var
utils
=
require
(
'./utils'
)
var
uiHelper
=
require
(
'./ui-helper'
)
function
Renderer
(
editor
,
web3
,
updateFiles
,
udapp
,
executionContext
,
formalVerificationEvent
,
compilerEvent
)
{
this
.
editor
=
editor
;
this
.
web3
=
web3
;
this
.
updateFiles
=
updateFiles
;
this
.
udapp
=
udapp
;
this
.
executionContext
=
executionContext
;
var
self
=
this
;
this
.
editor
=
editor
this
.
web3
=
web3
this
.
updateFiles
=
updateFiles
this
.
udapp
=
udapp
this
.
executionContext
=
executionContext
var
self
=
this
formalVerificationEvent
.
register
(
'compilationFinished'
,
this
,
function
(
success
,
message
,
container
,
noAnnotations
)
{
if
(
!
success
)
{
self
.
error
(
message
,
container
,
noAnnotations
)
;
self
.
error
(
message
,
container
,
noAnnotations
)
}
})
;
})
compilerEvent
.
register
(
'compilationFinished'
,
this
,
function
(
success
,
data
,
source
)
{
$
(
'#output'
).
empty
()
;
$
(
'#output'
).
empty
()
if
(
success
)
{
self
.
contracts
(
data
,
source
)
;
self
.
contracts
(
data
,
source
)
}
// NOTE: still need to display as there might be warnings
if
(
data
[
'error'
])
{
self
.
error
(
data
[
'error'
])
;
self
.
error
(
data
[
'error'
])
}
if
(
data
[
'errors'
])
{
data
[
'errors'
].
forEach
(
function
(
err
)
{
self
.
error
(
err
)
;
})
;
self
.
error
(
err
)
})
}
})
;
})
}
Renderer
.
prototype
.
error
=
function
(
message
,
container
,
noAnnotations
)
{
var
self
=
this
;
var
type
=
utils
.
errortype
(
message
)
;
var
$pre
=
$
(
'<pre />'
).
text
(
message
)
;
var
$error
=
$
(
'<div class="sol '
+
type
+
'"><div class="close"><i class="fa fa-close"></i></div></div>'
).
prepend
(
$pre
)
;
var
self
=
this
var
type
=
utils
.
errortype
(
message
)
var
$pre
=
$
(
'<pre />'
).
text
(
message
)
var
$error
=
$
(
'<div class="sol '
+
type
+
'"><div class="close"><i class="fa fa-close"></i></div></div>'
).
prepend
(
$pre
)
if
(
container
===
undefined
)
{
container
=
$
(
'#output'
)
;
container
=
$
(
'#output'
)
}
container
.
append
(
$error
)
;
var
err
=
message
.
match
(
/^
([^
:
]
*
)
:
([
0-9
]
*
)
:
(([
0-9
]
*
)
:
)?
/
)
;
container
.
append
(
$error
)
var
err
=
message
.
match
(
/^
([^
:
]
*
)
:
([
0-9
]
*
)
:
(([
0-9
]
*
)
:
)?
/
)
if
(
err
)
{
var
errFile
=
err
[
1
]
;
var
errLine
=
parseInt
(
err
[
2
],
10
)
-
1
;
var
errCol
=
err
[
4
]
?
parseInt
(
err
[
4
],
10
)
:
0
;
var
errFile
=
err
[
1
]
var
errLine
=
parseInt
(
err
[
2
],
10
)
-
1
var
errCol
=
err
[
4
]
?
parseInt
(
err
[
4
],
10
)
:
0
if
(
!
noAnnotations
&&
(
errFile
===
''
||
errFile
===
utils
.
fileNameFromKey
(
self
.
editor
.
getCacheFile
())))
{
self
.
editor
.
addAnnotation
({
row
:
errLine
,
column
:
errCol
,
text
:
message
,
type
:
type
})
;
})
}
$error
.
click
(
function
(
ev
)
{
if
(
errFile
!==
''
&&
errFile
!==
utils
.
fileNameFromKey
(
self
.
editor
.
getCacheFile
())
&&
self
.
editor
.
hasFile
(
errFile
))
{
// Switch to file
self
.
editor
.
setCacheFile
(
utils
.
fileKey
(
errFile
))
;
self
.
updateFiles
()
;
self
.
editor
.
setCacheFile
(
utils
.
fileKey
(
errFile
))
self
.
updateFiles
()
// @TODO could show some error icon in files with errors
}
self
.
editor
.
handleErrorClick
(
errLine
,
errCol
)
;
})
;
self
.
editor
.
handleErrorClick
(
errLine
,
errCol
)
})
$error
.
find
(
'.close'
).
click
(
function
(
ev
)
{
ev
.
preventDefault
()
;
$error
.
remove
()
;
return
false
;
})
;
ev
.
preventDefault
()
$error
.
remove
()
return
false
})
}
}
;
}
Renderer
.
prototype
.
contracts
=
function
(
data
,
source
)
{
var
udappContracts
=
[]
;
var
udappContracts
=
[]
for
(
var
contractName
in
data
.
contracts
)
{
var
contract
=
data
.
contracts
[
contractName
]
;
var
contract
=
data
.
contracts
[
contractName
]
udappContracts
.
push
({
name
:
contractName
,
interface
:
contract
[
'interface'
],
bytecode
:
contract
.
bytecode
})
;
})
}
// rendering function used by udapp. they need data and source
var
combined
=
function
(
contractName
,
jsonInterface
,
bytecode
)
{
return
JSON
.
stringify
([{
name
:
contractName
,
interface
:
jsonInterface
,
bytecode
:
bytecode
}])
;
}
;
return
JSON
.
stringify
([{
name
:
contractName
,
interface
:
jsonInterface
,
bytecode
:
bytecode
}])
}
var
renderOutputModifier
=
function
(
contractName
,
$contractOutput
)
{
var
contract
=
data
.
contracts
[
contractName
]
;
var
contract
=
data
.
contracts
[
contractName
]
if
(
contract
.
bytecode
)
{
$contractOutput
.
append
(
uiHelper
.
textRow
(
'Bytecode'
,
contract
.
bytecode
))
;
$contractOutput
.
append
(
uiHelper
.
textRow
(
'Bytecode'
,
contract
.
bytecode
))
}
$contractOutput
.
append
(
uiHelper
.
textRow
(
'Interface'
,
contract
[
'interface'
]))
;
$contractOutput
.
append
(
uiHelper
.
textRow
(
'Interface'
,
contract
[
'interface'
]))
if
(
contract
.
bytecode
)
{
$contractOutput
.
append
(
uiHelper
.
textRow
(
'Web3 deploy'
,
uiHelper
.
gethDeploy
(
contractName
.
toLowerCase
(),
contract
[
'interface'
],
contract
.
bytecode
),
'deploy'
))
;
$contractOutput
.
append
(
uiHelper
.
textRow
(
'uDApp'
,
combined
(
contractName
,
contract
[
'interface'
],
contract
.
bytecode
),
'deploy'
))
;
$contractOutput
.
append
(
uiHelper
.
textRow
(
'Web3 deploy'
,
uiHelper
.
gethDeploy
(
contractName
.
toLowerCase
(),
contract
[
'interface'
],
contract
.
bytecode
),
'deploy'
))
$contractOutput
.
append
(
uiHelper
.
textRow
(
'uDApp'
,
combined
(
contractName
,
contract
[
'interface'
],
contract
.
bytecode
),
'deploy'
))
}
var
ctrSource
=
getSource
(
contractName
,
source
,
data
)
;
return
$contractOutput
.
append
(
uiHelper
.
getDetails
(
contract
,
ctrSource
,
contractName
))
;
}
;
var
ctrSource
=
getSource
(
contractName
,
source
,
data
)
return
$contractOutput
.
append
(
uiHelper
.
getDetails
(
contract
,
ctrSource
,
contractName
))
}
// //
var
self
=
this
;
var
self
=
this
var
getSource
=
function
(
contractName
,
source
,
data
)
{
var
currentFile
=
utils
.
fileNameFromKey
(
self
.
editor
.
getCacheFile
())
;
return
source
.
sources
[
currentFile
]
;
}
;
var
currentFile
=
utils
.
fileNameFromKey
(
self
.
editor
.
getCacheFile
())
return
source
.
sources
[
currentFile
]
}
var
getAddress
=
function
()
{
return
$
(
'#txorigin'
).
val
()
;
};
var
getAddress
=
function
()
{
return
$
(
'#txorigin'
).
val
()
}
var
getValue
=
function
()
{
var
comp
=
$
(
'#value'
).
val
().
split
(
' '
)
;
return
self
.
executionContext
.
web3
().
toWei
(
comp
[
0
],
comp
.
slice
(
1
).
join
(
' '
))
;
}
;
var
comp
=
$
(
'#value'
).
val
().
split
(
' '
)
return
self
.
executionContext
.
web3
().
toWei
(
comp
[
0
],
comp
.
slice
(
1
).
join
(
' '
))
}
var
getGasLimit
=
function
()
{
return
$
(
'#gasLimit'
).
val
()
;
};
var
getGasLimit
=
function
()
{
return
$
(
'#gasLimit'
).
val
()
}
this
.
udapp
.
reset
(
udappContracts
,
getAddress
,
getValue
,
getGasLimit
,
renderOutputModifier
)
;
this
.
udapp
.
reset
(
udappContracts
,
getAddress
,
getValue
,
getGasLimit
,
renderOutputModifier
)
var
$contractOutput
=
this
.
udapp
.
render
()
;
var
$contractOutput
=
this
.
udapp
.
render
()
var
$txOrigin
=
$
(
'#txorigin'
)
;
var
$txOrigin
=
$
(
'#txorigin'
)
this
.
udapp
.
getAccounts
(
function
(
err
,
accounts
)
{
if
(
err
)
{
self
.
error
(
err
.
message
)
;
self
.
error
(
err
.
message
)
}
if
(
accounts
&&
accounts
[
0
])
{
$txOrigin
.
empty
()
;
for
(
var
a
in
accounts
)
{
$txOrigin
.
append
(
$
(
'<option />'
).
val
(
accounts
[
a
]).
text
(
accounts
[
a
]))
;
}
$txOrigin
.
val
(
accounts
[
0
])
;
$txOrigin
.
empty
()
for
(
var
a
in
accounts
)
{
$txOrigin
.
append
(
$
(
'<option />'
).
val
(
accounts
[
a
]).
text
(
accounts
[
a
]))
}
$txOrigin
.
val
(
accounts
[
0
])
}
else
{
$txOrigin
.
val
(
'unknown'
)
;
$txOrigin
.
val
(
'unknown'
)
}
})
;
})
$contractOutput
.
find
(
'.title'
).
click
(
function
(
ev
)
{
$
(
this
).
closest
(
'.contract'
).
toggleClass
(
'hide'
)
;
});
$
(
'#output'
).
append
(
$contractOutput
)
;
$
(
'.col2 input,textarea'
).
click
(
function
()
{
this
.
select
()
;
});
}
;
$contractOutput
.
find
(
'.title'
).
click
(
function
(
ev
)
{
$
(
this
).
closest
(
'.contract'
).
toggleClass
(
'hide'
)
})
$
(
'#output'
).
append
(
$contractOutput
)
$
(
'.col2 input,textarea'
).
click
(
function
()
{
this
.
select
()
})
}
module
.
exports
=
Renderer
;
module
.
exports
=
Renderer
src/app/storage.js
View file @
2126391e
/* global chrome, confirm */
'use strict'
;
'use strict'
var
utils
=
require
(
'./utils'
)
;
var
utils
=
require
(
'./utils'
)
function
Storage
(
updateFiles
)
{
var
EDITOR_SIZE_CACHE_KEY
=
'editor-size-cache'
;
var
EDITOR_SIZE_CACHE_KEY
=
'editor-size-cache'
this
.
rename
=
function
(
originalName
,
newName
)
{
var
content
=
this
.
get
(
originalName
)
;
this
.
set
(
newName
,
content
)
;
this
.
remove
(
originalName
)
;
}
;
var
content
=
this
.
get
(
originalName
)
this
.
set
(
newName
,
content
)
this
.
remove
(
originalName
)
}
this
.
remove
=
function
(
name
)
{
window
.
localStorage
.
removeItem
(
name
)
;
}
;
window
.
localStorage
.
removeItem
(
name
)
}
this
.
setEditorSize
=
function
(
size
)
{
this
.
set
(
EDITOR_SIZE_CACHE_KEY
,
size
)
;
}
;
this
.
set
(
EDITOR_SIZE_CACHE_KEY
,
size
)
}
this
.
getEditorSize
=
function
()
{
return
this
.
get
(
EDITOR_SIZE_CACHE_KEY
)
;
}
;
return
this
.
get
(
EDITOR_SIZE_CACHE_KEY
)
}
this
.
getFileContent
=
function
(
key
)
{
return
this
.
get
(
utils
.
fileKey
(
key
))
;
}
;
return
this
.
get
(
utils
.
fileKey
(
key
))
}
this
.
exists
=
function
(
key
)
{
return
!!
this
.
get
(
key
)
;
}
;
return
!!
this
.
get
(
key
)
}
this
.
set
=
function
(
key
,
content
)
{
window
.
localStorage
.
setItem
(
key
,
content
)
;
}
;
window
.
localStorage
.
setItem
(
key
,
content
)
}
this
.
get
=
function
(
key
)
{
return
window
.
localStorage
.
getItem
(
key
)
;
}
;
return
window
.
localStorage
.
getItem
(
key
)
}
this
.
keys
=
function
()
{
// NOTE: this is a workaround for some browsers
return
Object
.
keys
(
window
.
localStorage
).
filter
(
function
(
item
)
{
return
item
!==
null
&&
item
!==
undefined
;
});
}
;
return
Object
.
keys
(
window
.
localStorage
).
filter
(
function
(
item
)
{
return
item
!==
null
&&
item
!==
undefined
})
}
this
.
loadFile
=
function
(
filename
,
content
)
{
if
(
this
.
exists
(
filename
)
&&
this
.
get
(
filename
)
!==
content
)
{
var
count
=
''
;
while
(
this
.
exists
(
filename
+
count
))
count
=
count
-
1
;
this
.
rename
(
filename
,
filename
+
count
)
;
var
count
=
''
while
(
this
.
exists
(
filename
+
count
))
count
=
count
-
1
this
.
rename
(
filename
,
filename
+
count
)
}
this
.
set
(
filename
,
content
)
;
}
;
this
.
set
(
filename
,
content
)
}
this
.
sync
=
function
()
{
if
(
typeof
chrome
===
'undefined'
||
!
chrome
||
!
chrome
.
storage
||
!
chrome
.
storage
.
sync
)
{
return
;
return
}
var
obj
=
{}
;
var
done
=
false
;
var
count
=
0
;
var
obj
=
{}
var
done
=
false
var
count
=
0
function
check
(
key
)
{
chrome
.
storage
.
sync
.
get
(
key
,
function
(
resp
)
{
console
.
log
(
'comparing to cloud'
,
key
,
resp
)
;
console
.
log
(
'comparing to cloud'
,
key
,
resp
)
if
(
typeof
resp
[
key
]
!==
'undefined'
&&
obj
[
key
]
!==
resp
[
key
]
&&
confirm
(
'Overwrite "'
+
utils
.
fileNameFromKey
(
key
)
+
'"? Click Ok to overwrite local file with file from cloud. Cancel will push your local file to the cloud.'
))
{
console
.
log
(
'Overwriting'
,
key
)
;
window
.
localStorage
.
setItem
(
key
,
resp
[
key
])
;
updateFiles
()
;
console
.
log
(
'Overwriting'
,
key
)
window
.
localStorage
.
setItem
(
key
,
resp
[
key
])
updateFiles
()
}
else
{
console
.
log
(
'add to obj'
,
obj
,
key
)
;
obj
[
key
]
=
window
.
localStorage
[
key
]
;
console
.
log
(
'add to obj'
,
obj
,
key
)
obj
[
key
]
=
window
.
localStorage
[
key
]
}
done
++
;
done
++
if
(
done
>=
count
)
{
chrome
.
storage
.
sync
.
set
(
obj
,
function
()
{
console
.
log
(
'updated cloud files with: '
,
obj
,
this
,
arguments
)
;
})
;
console
.
log
(
'updated cloud files with: '
,
obj
,
this
,
arguments
)
})
}
})
;
})
}
for
(
var
y
in
window
.
localStorage
)
{
console
.
log
(
'checking'
,
y
)
;
obj
[
y
]
=
window
.
localStorage
.
getItem
(
y
)
;
console
.
log
(
'checking'
,
y
)
obj
[
y
]
=
window
.
localStorage
.
getItem
(
y
)
if
(
!
utils
.
isCachedFile
(
y
))
{
continue
;
continue
}
count
++
;
check
(
y
)
;
count
++
check
(
y
)
}
}
;
}
}
module
.
exports
=
Storage
;
module
.
exports
=
Storage
src/app/ui-helper.js
View file @
2126391e
'use strict'
;
'use strict'
var
$
=
require
(
'jquery'
)
;
var
$
=
require
(
'jquery'
)
module
.
exports
=
{
tableRowItems
:
function
(
first
,
second
,
cls
)
{
return
$
(
'<div class="crow"/>'
)
.
addClass
(
cls
)
.
append
(
$
(
'<div class="col1">'
).
append
(
first
))
.
append
(
$
(
'<div class="col2">'
).
append
(
second
))
;
.
append
(
$
(
'<div class="col2">'
).
append
(
second
))
},
tableRow
:
function
(
description
,
data
)
{
return
this
.
tableRowItems
(
$
(
'<span/>'
).
text
(
description
),
$
(
'<input readonly="readonly"/>'
).
val
(
data
))
;
$
(
'<input readonly="readonly"/>'
).
val
(
data
))
},
textRow
:
function
(
description
,
data
,
cls
)
{
return
this
.
tableRowItems
(
$
(
'<strong/>'
).
text
(
description
),
$
(
'<textarea readonly="readonly" class="gethDeployText"/>'
).
val
(
data
),
cls
)
;
cls
)
},
preRow
:
function
(
description
,
data
)
{
return
this
.
tableRowItems
(
$
(
'<span/>'
).
text
(
description
),
$
(
'<pre/>'
).
text
(
data
)
)
;
)
},
formatAssemblyText
:
function
(
asm
,
prefix
,
source
)
{
var
self
=
this
;
var
self
=
this
if
(
typeof
asm
===
typeof
''
||
asm
===
null
||
asm
===
undefined
)
{
return
prefix
+
asm
+
'
\
n'
;
return
prefix
+
asm
+
'
\
n'
}
var
text
=
prefix
+
'.code
\
n'
;
var
text
=
prefix
+
'.code
\
n'
$
.
each
(
asm
[
'.code'
],
function
(
i
,
item
)
{
var
v
=
item
.
value
===
undefined
?
''
:
item
.
value
;
var
src
=
''
;
var
v
=
item
.
value
===
undefined
?
''
:
item
.
value
var
src
=
''
if
(
item
.
begin
!==
undefined
&&
item
.
end
!==
undefined
)
{
src
=
source
.
slice
(
item
.
begin
,
item
.
end
).
replace
(
'
\
n'
,
'
\\
n'
,
'g'
)
;
src
=
source
.
slice
(
item
.
begin
,
item
.
end
).
replace
(
'
\
n'
,
'
\\
n'
,
'g'
)
}
if
(
src
.
length
>
30
)
{
src
=
src
.
slice
(
0
,
30
)
+
'...'
;
src
=
src
.
slice
(
0
,
30
)
+
'...'
}
if
(
item
.
name
!==
'tag'
)
{
text
+=
' '
;
text
+=
' '
}
text
+=
prefix
+
item
.
name
+
' '
+
v
+
'
\
t
\
t
\
t'
+
src
+
'
\
n'
;
})
;
text
+=
prefix
+
'.data
\
n'
;
text
+=
prefix
+
item
.
name
+
' '
+
v
+
'
\
t
\
t
\
t'
+
src
+
'
\
n'
})
text
+=
prefix
+
'.data
\
n'
if
(
asm
[
'.data'
])
{
$
.
each
(
asm
[
'.data'
],
function
(
i
,
item
)
{
text
+=
' '
+
prefix
+
''
+
i
+
':
\
n'
;
text
+=
self
.
formatAssemblyText
(
item
,
prefix
+
' '
,
source
)
;
})
;
text
+=
' '
+
prefix
+
''
+
i
+
':
\
n'
text
+=
self
.
formatAssemblyText
(
item
,
prefix
+
' '
,
source
)
})
}
return
text
;
return
text
},
gethDeploy
:
function
(
contractName
,
jsonInterface
,
bytecode
)
{
var
code
=
''
;
var
funABI
=
this
.
getConstructorInterface
(
JSON
.
parse
(
jsonInterface
))
;
var
code
=
''
var
funABI
=
this
.
getConstructorInterface
(
JSON
.
parse
(
jsonInterface
))
funABI
.
inputs
.
forEach
(
function
(
inp
)
{
code
+=
'var '
+
inp
.
name
+
' = /* var of type '
+
inp
.
type
+
' here */ ;
\
n'
;
})
;
code
+=
'var '
+
inp
.
name
+
' = /* var of type '
+
inp
.
type
+
' here */ ;
\
n'
})
code
+=
'var '
+
contractName
+
'Contract = web3.eth.contract('
+
jsonInterface
.
replace
(
'
\
n'
,
''
)
+
');'
+
'
\
nvar '
+
contractName
+
' = '
+
contractName
+
'Contract.new('
;
'
\
nvar '
+
contractName
+
' = '
+
contractName
+
'Contract.new('
funABI
.
inputs
.
forEach
(
function
(
inp
)
{
code
+=
'
\
n '
+
inp
.
name
+
','
;
})
;
code
+=
'
\
n '
+
inp
.
name
+
','
})
code
+=
'
\
n {'
+
'
\
n from: web3.eth.accounts[0], '
+
...
...
@@ -84,90 +84,90 @@ module.exports = {
"
\
n if (typeof contract.address !== 'undefined') {"
+
"
\
n console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);"
+
'
\
n }'
+
'
\
n })'
;
'
\
n })'
return
code
;
return
code
},
getConstructorInterface
:
function
(
abi
)
{
var
funABI
=
{
'name'
:
''
,
'inputs'
:
[],
'type'
:
'constructor'
,
'outputs'
:
[]
}
;
var
funABI
=
{
'name'
:
''
,
'inputs'
:
[],
'type'
:
'constructor'
,
'outputs'
:
[]
}
for
(
var
i
=
0
;
i
<
abi
.
length
;
i
++
)
{
if
(
abi
[
i
].
type
===
'constructor'
)
{
funABI
.
inputs
=
abi
[
i
].
inputs
||
[]
;
break
;
funABI
.
inputs
=
abi
[
i
].
inputs
||
[]
break
}
}
return
funABI
;
return
funABI
},
formatGasEstimates
:
function
(
data
)
{
// FIXME: the whole gasEstimates object should be nil instead
if
(
data
.
creation
===
undefined
&&
data
.
external
===
undefined
&&
data
.
internal
===
undefined
)
{
return
;
return
}
var
gasToText
=
function
(
g
)
{
return
g
===
null
?
'unknown'
:
g
;
}
;
return
g
===
null
?
'unknown'
:
g
}
var
text
=
''
;
var
fun
;
var
text
=
''
var
fun
if
(
'creation'
in
data
)
{
text
+=
'Creation: '
+
gasToText
(
data
.
creation
[
0
])
+
' + '
+
gasToText
(
data
.
creation
[
1
])
+
'
\
n'
;
text
+=
'Creation: '
+
gasToText
(
data
.
creation
[
0
])
+
' + '
+
gasToText
(
data
.
creation
[
1
])
+
'
\
n'
}
if
(
'external'
in
data
)
{
text
+=
'External:
\
n'
;
text
+=
'External:
\
n'
for
(
fun
in
data
.
external
)
{
text
+=
' '
+
fun
+
': '
+
gasToText
(
data
.
external
[
fun
])
+
'
\
n'
;
text
+=
' '
+
fun
+
': '
+
gasToText
(
data
.
external
[
fun
])
+
'
\
n'
}
}
if
(
'internal'
in
data
)
{
text
+=
'Internal:
\
n'
;
text
+=
'Internal:
\
n'
for
(
fun
in
data
.
internal
)
{
text
+=
' '
+
fun
+
': '
+
gasToText
(
data
.
internal
[
fun
])
+
'
\
n'
;
text
+=
' '
+
fun
+
': '
+
gasToText
(
data
.
internal
[
fun
])
+
'
\
n'
}
}
return
text
;
return
text
},
detailsOpen
:
{},
getDetails
:
function
(
contract
,
source
,
contractName
)
{
var
button
=
$
(
'<button>Toggle Details</button>'
)
;
var
details
=
$
(
'<div style="display: none;"/>'
)
;
var
button
=
$
(
'<button>Toggle Details</button>'
)
var
details
=
$
(
'<div style="display: none;"/>'
)
var
funHashes
=
''
;
var
funHashes
=
''
for
(
var
fun
in
contract
.
functionHashes
)
{
funHashes
+=
contract
.
functionHashes
[
fun
]
+
' '
+
fun
+
'
\
n'
;
funHashes
+=
contract
.
functionHashes
[
fun
]
+
' '
+
fun
+
'
\
n'
}
details
.
append
(
this
.
preRow
(
'Functions'
,
funHashes
))
;
details
.
append
(
this
.
preRow
(
'Functions'
,
funHashes
))
var
gasEstimates
=
this
.
formatGasEstimates
(
contract
.
gasEstimates
)
;
var
gasEstimates
=
this
.
formatGasEstimates
(
contract
.
gasEstimates
)
if
(
gasEstimates
)
{
details
.
append
(
this
.
preRow
(
'Gas Estimates'
,
gasEstimates
))
;
details
.
append
(
this
.
preRow
(
'Gas Estimates'
,
gasEstimates
))
}
if
(
contract
.
runtimeBytecode
&&
contract
.
runtimeBytecode
.
length
>
0
)
{
details
.
append
(
this
.
tableRow
(
'Runtime Bytecode'
,
contract
.
runtimeBytecode
))
;
details
.
append
(
this
.
tableRow
(
'Runtime Bytecode'
,
contract
.
runtimeBytecode
))
}
if
(
contract
.
opcodes
!==
undefined
&&
contract
.
opcodes
!==
''
)
{
details
.
append
(
this
.
tableRow
(
'Opcodes'
,
contract
.
opcodes
))
;
details
.
append
(
this
.
tableRow
(
'Opcodes'
,
contract
.
opcodes
))
}
if
(
contract
.
assembly
!==
null
)
{
details
.
append
(
this
.
preRow
(
'Assembly'
,
this
.
formatAssemblyText
(
contract
.
assembly
,
''
,
source
)))
;
details
.
append
(
this
.
preRow
(
'Assembly'
,
this
.
formatAssemblyText
(
contract
.
assembly
,
''
,
source
)))
}
var
self
=
this
;
var
self
=
this
button
.
click
(
function
()
{
self
.
detailsOpen
[
contractName
]
=
!
self
.
detailsOpen
[
contractName
]
;
details
.
toggle
()
;
})
;
self
.
detailsOpen
[
contractName
]
=
!
self
.
detailsOpen
[
contractName
]
details
.
toggle
()
})
if
(
this
.
detailsOpen
[
contractName
])
{
details
.
show
()
;
details
.
show
()
}
return
$
(
'<div class="contractDetails"/>'
).
append
(
button
).
append
(
details
)
;
return
$
(
'<div class="contractDetails"/>'
).
append
(
button
).
append
(
details
)
}
}
;
}
src/app/utils.js
View file @
2126391e
'use strict'
;
'use strict'
var
SOL_CACHE_FILE_PREFIX
=
'sol-cache-file-'
;
var
SOL_CACHE_FILE_PREFIX
=
'sol-cache-file-'
function
getCacheFilePrefix
()
{
return
SOL_CACHE_FILE_PREFIX
;
return
SOL_CACHE_FILE_PREFIX
}
function
isCachedFile
(
name
)
{
return
name
.
indexOf
(
getCacheFilePrefix
(),
0
)
===
0
;
return
name
.
indexOf
(
getCacheFilePrefix
(),
0
)
===
0
}
function
fileKey
(
name
)
{
return
getCacheFilePrefix
()
+
name
;
return
getCacheFilePrefix
()
+
name
}
function
fileNameFromKey
(
key
)
{
return
key
.
replace
(
getCacheFilePrefix
(),
''
)
;
return
key
.
replace
(
getCacheFilePrefix
(),
''
)
}
function
errortype
(
message
)
{
return
message
.
match
(
/^.*:
[
0-9
]
*:
[
0-9
]
* Warning: /
)
?
'warning'
:
'error'
;
return
message
.
match
(
/^.*:
[
0-9
]
*:
[
0-9
]
* Warning: /
)
?
'warning'
:
'error'
}
module
.
exports
=
{
...
...
@@ -27,4 +27,4 @@ module.exports = {
fileKey
:
fileKey
,
fileNameFromKey
:
fileNameFromKey
,
errortype
:
errortype
}
;
}
src/index.js
View file @
2126391e
'use strict'
;
'use strict'
require
(
'es6-shim'
)
;
var
app
=
require
(
'./app.js'
)
;
var
$
=
require
(
'jquery'
)
;
require
(
'es6-shim'
)
var
app
=
require
(
'./app.js'
)
var
$
=
require
(
'jquery'
)
$
(
document
).
ready
(
function
()
{
app
.
run
()
;
});
$
(
document
).
ready
(
function
()
{
app
.
run
()
})
src/lib/eventManager.js
View file @
2126391e
'use strict'
;
'use strict'
function
eventManager
()
{
this
.
registered
=
{}
;
this
.
registered
=
{}
}
/*
...
...
@@ -14,17 +14,17 @@ function eventManager () {
*/
eventManager
.
prototype
.
unregister
=
function
(
eventName
,
obj
,
func
)
{
if
(
obj
instanceof
Function
)
{
func
=
obj
;
obj
=
{}
;
func
=
obj
obj
=
{}
}
for
(
var
reg
in
this
.
registered
[
eventName
])
{
if
(
this
.
registered
[
eventName
][
reg
]
&&
this
.
registered
[
eventName
][
reg
].
obj
===
obj
&&
(
!
func
||
this
.
registered
[
eventName
][
reg
].
func
===
func
))
{
this
.
registered
[
eventName
].
splice
(
reg
,
1
)
;
return
;
this
.
registered
[
eventName
].
splice
(
reg
,
1
)
return
}
}
}
;
}
/*
* Register a new listenner.
...
...
@@ -36,17 +36,17 @@ eventManager.prototype.unregister = function (eventName, obj, func) {
*/
eventManager
.
prototype
.
register
=
function
(
eventName
,
obj
,
func
)
{
if
(
!
this
.
registered
[
eventName
])
{
this
.
registered
[
eventName
]
=
[]
;
this
.
registered
[
eventName
]
=
[]
}
if
(
obj
instanceof
Function
)
{
func
=
obj
;
obj
=
{}
;
func
=
obj
obj
=
{}
}
this
.
registered
[
eventName
].
push
({
obj
:
obj
,
func
:
func
})
;
}
;
})
}
/*
* trigger event.
...
...
@@ -57,9 +57,9 @@ eventManager.prototype.register = function (eventName, obj, func) {
*/
eventManager
.
prototype
.
trigger
=
function
(
eventName
,
args
)
{
for
(
var
listener
in
this
.
registered
[
eventName
])
{
var
l
=
this
.
registered
[
eventName
][
listener
]
;
l
.
func
.
apply
(
l
.
obj
,
args
)
;
var
l
=
this
.
registered
[
eventName
][
listener
]
l
.
func
.
apply
(
l
.
obj
,
args
)
}
}
;
}
module
.
exports
=
eventManager
;
module
.
exports
=
eventManager
src/universal-dapp.js
View file @
2126391e
This diff is collapsed.
Click to expand it.
test-browser/helpers/contracts.js
View file @
2126391e
module
.
exports
=
{
checkCompiledContracts
:
function
(
browser
,
compiled
,
callback
)
{
browser
.
execute
(
function
()
{
var
contracts
=
document
.
querySelectorAll
(
'.udapp .contract'
)
;
var
ret
=
[]
;
var
contracts
=
document
.
querySelectorAll
(
'.udapp .contract'
)
var
ret
=
[]
for
(
var
k
in
contracts
)
{
var
el
=
contracts
[
k
]
;
var
el
=
contracts
[
k
]
if
(
el
.
querySelector
)
{
ret
.
push
({
name
:
el
.
querySelector
(
'.title'
).
innerText
.
replace
(
el
.
querySelector
(
'.size'
).
innerText
,
''
).
replace
(
/
(\t)
|
(\r)
|
(\n)
/g
,
''
)
// IE/firefox add \r\n
})
;
})
}
}
return
ret
;
return
ret
},
[
''
],
function
(
result
)
{
browser
.
assert
.
equal
(
result
.
value
.
length
,
compiled
.
length
)
;
browser
.
assert
.
equal
(
result
.
value
.
length
,
compiled
.
length
)
result
.
value
.
map
(
function
(
item
,
i
)
{
browser
.
assert
.
equal
(
item
.
name
,
compiled
[
i
])
;
})
;
callback
()
;
})
;
browser
.
assert
.
equal
(
item
.
name
,
compiled
[
i
])
})
callback
()
})
}
}
;
}
test-browser/mockcompiler/compiler.js
View file @
2126391e
var
Module
=
{
// eslint-disable-line
cwrap
:
function
()
{
return
arguments
[
0
]
===
'version'
?
version
:
compile
;
},
cwrap
:
function
()
{
return
arguments
[
0
]
===
'version'
?
version
:
compile
},
writeStringToMemory
:
function
()
{},
setValue
:
function
()
{},
Pointer_stringify
:
function
()
{},
...
...
@@ -10,32 +10,32 @@ var Module = { // eslint-disable-line
_compileJSONMulti
:
{},
_compileJSONCallback
:
{},
_compileJSON
:
{}
}
;
}
function
compile
(
source
,
optimization
,
missingInputs
)
{
if
(
typeof
source
===
'string'
)
{
source
=
JSON
.
parse
(
source
)
;
source
=
JSON
.
parse
(
source
)
}
var
key
=
optimization
.
toString
()
;
var
key
=
optimization
.
toString
()
for
(
var
k
in
source
.
sources
)
{
key
+=
k
+
source
.
sources
[
k
]
;
key
+=
k
+
source
.
sources
[
k
]
}
key
=
key
.
replace
(
/
(\t)
|
(\n)
|
(
)
/g
,
''
)
;
var
data
=
mockData
[
key
]
;
// eslint-disable-line
key
=
key
.
replace
(
/
(\t)
|
(\n)
|
(
)
/g
,
''
)
var
data
=
mockData
[
key
]
// eslint-disable-line
if
(
data
===
undefined
)
{
return
JSON
.
stringify
({
errors
:
[
'mock compiler: source not found'
]
})
;
})
}
else
{
data
.
missingInputs
.
map
(
function
(
item
,
i
)
{
if
(
missingInputs
)
{
missingInputs
(
item
)
;
missingInputs
(
item
)
}
})
;
})
}
return
JSON
.
stringify
(
data
.
result
)
;
return
JSON
.
stringify
(
data
.
result
)
}
function
version
()
{
return
'mock compiler'
;
return
'mock compiler'
}
test-browser/mockcompiler/requests.js
View file @
2126391e
...
...
@@ -6,72 +6,72 @@ module.exports = {
},
'ballot'
:
{
'sources'
:
{
'Untitled'
:
`pragma solidity ^0.4.0
;
'Untitled'
:
`pragma solidity ^0.4.0
contract Ballot {
struct Voter {
uint weight
;
bool voted
;
uint8 vote
;
address delegate
;
uint weight
bool voted
uint8 vote
address delegate
}
struct Proposal {
uint voteCount
;
uint voteCount
}
address chairperson
;
mapping(address => Voter) voters
;
Proposal[] proposals
;
address chairperson
mapping(address => Voter) voters
Proposal[] proposals
/// Create a new ballot with $(_numProposals) different proposals.
function Ballot(uint8 _numProposals) {
chairperson = msg.sender
;
voters[chairperson].weight = 1
;
proposals.length = _numProposals
;
chairperson = msg.sender
voters[chairperson].weight = 1
proposals.length = _numProposals
}
/// Give $(voter) the right to vote on this ballot.
/// May only be called by $(chairperson).
function giveRightToVote(address voter) {
if (msg.sender != chairperson || voters[voter].voted) return
;
voters[voter].weight = 1
;
if (msg.sender != chairperson || voters[voter].voted) return
voters[voter].weight = 1
}
/// Delegate your vote to the voter $(to).
function delegate(address to) {
Voter sender = voters[msg.sender]
;
// assigns reference
if (sender.voted) return
;
Voter sender = voters[msg.sender] // assigns reference
if (sender.voted) return
while (voters[to].delegate != address(0) && voters[to].delegate != msg.sender)
to = voters[to].delegate
;
if (to == msg.sender) return
;
sender.voted = true
;
sender.delegate = to
;
Voter delegate = voters[to]
;
to = voters[to].delegate
if (to == msg.sender) return
sender.voted = true
sender.delegate = to
Voter delegate = voters[to]
if (delegate.voted)
proposals[delegate.vote].voteCount += sender.weight
;
proposals[delegate.vote].voteCount += sender.weight
else
delegate.weight += sender.weight
;
delegate.weight += sender.weight
}
/// Give a single vote to proposal $(proposal).
function vote(uint8 proposal) {
Voter sender = voters[msg.sender]
;
if (sender.voted || proposal >= proposals.length) return
;
sender.voted = true
;
sender.vote = proposal
;
proposals[proposal].voteCount += sender.weight
;
Voter sender = voters[msg.sender]
if (sender.voted || proposal >= proposals.length) return
sender.voted = true
sender.vote = proposal
proposals[proposal].voteCount += sender.weight
}
function winningProposal() constant returns (uint8 winningProposal) {
uint256 winningVoteCount = 0
;
uint256 winningVoteCount = 0
for (uint8 proposal = 0; proposal < proposals.length; proposal++)
if (proposals[proposal].voteCount > winningVoteCount) {
winningVoteCount = proposals[proposal].voteCount
;
winningProposal = proposal
;
winningVoteCount = proposals[proposal].voteCount
winningProposal = proposal
}
}
}
`
}
}
}
;
}
test-browser/tests/ballot.js
View file @
2126391e
'use strict'
;
var
testData
=
require
(
'../mockcompiler/requests'
)
;
// var contractHelper = require('../helpers/contracts')
;
'use strict'
var
testData
=
require
(
'../mockcompiler/requests'
)
// var contractHelper = require('../helpers/contracts')
module
.
exports
=
{
'Ballot'
:
function
(
browser
)
{
runTests
(
browser
,
testData
)
;
runTests
(
browser
,
testData
)
}
}
;
}
function
runTests
(
browser
,
testData
)
{
browser
.
url
(
'http://127.0.0.1:8080/#version=builtin'
)
.
waitForElementVisible
(
'.newFile'
,
10000
);
browser
.
assert
.
notEqual
(
testData
,
null
);
// TODO add Ballot tests. -> setValue('#input textarea', ... ) is not working properly with that contract.
/* testBallot(browser, testData.ballot.sources.Untitled, function () {
browser.end();
});*/
.
waitForElementVisible
(
'.newFile'
,
10000
)
browser
.
assert
.
notEqual
(
testData
,
null
)
// TODO add Ballot tests. -> setValue('#input textarea', ... ) is not working properly with that contract.
/*
testBallot(browser, testData.ballot.sources.Untitled, function () {
browser.end()
});
*/
}
/*
...
...
@@ -25,7 +27,8 @@ function testBallot (browser, contract, callback) {
.click('.newFile')
.clearValue('#input textarea')
.setValue('#input textarea', contract, function () {
browser.pause('10000');
contractHelper.checkCompiledContracts(browser, ['Ballot'], callback);
});
}*/
browser.pause('10000')
contractHelper.checkCompiledContracts(browser, ['Ballot'], callback)
})
}
*/
test-browser/tests/debugger.js
View file @
2126391e
'use strict'
;
'use strict'
module
.
exports
=
{
'Debugger Render'
:
function
(
browser
)
{
...
...
@@ -6,6 +6,6 @@ module.exports = {
.
url
(
'http://127.0.0.1:8080/#version=builtin'
)
.
waitForElementPresent
(
'#debugger'
,
10000
)
.
waitForElementPresent
(
'#debugger #slider'
,
10000
)
.
end
()
;
.
end
()
}
}
;
}
test-browser/tests/new-file-test.js
View file @
2126391e
'use strict'
;
'use strict'
module
.
exports
=
{
'New file test'
:
function
(
browser
)
{
...
...
@@ -8,6 +8,6 @@ module.exports = {
.
click
(
'.newFile'
)
.
pause
(
'10000'
)
.
assert
.
containsText
(
'.active'
,
'Untitled'
)
.
end
()
;
.
end
()
}
}
;
}
test-browser/tests/simpleContract.js
View file @
2126391e
'use strict'
;
var
testData
=
require
(
'../mockcompiler/requests'
)
;
var
contractHelper
=
require
(
'../helpers/contracts'
)
;
'use strict'
var
testData
=
require
(
'../mockcompiler/requests'
)
var
contractHelper
=
require
(
'../helpers/contracts'
)
module
.
exports
=
{
'Simple Contract'
:
function
(
browser
)
{
runTests
(
browser
,
testData
)
;
runTests
(
browser
,
testData
)
}
}
;
}
function
runTests
(
browser
,
testData
)
{
browser
.
url
(
'http://127.0.0.1:8080/#version=builtin'
)
.
waitForElementVisible
(
'.newFile'
,
10000
)
;
browser
.
assert
.
notEqual
(
testData
,
null
)
;
.
waitForElementVisible
(
'.newFile'
,
10000
)
browser
.
assert
.
notEqual
(
testData
,
null
)
testSimpleContract
(
browser
,
testData
.
testSimpleContract
.
sources
.
Untitled
,
function
()
{
browser
.
end
()
;
})
;
browser
.
end
()
})
}
function
testSimpleContract
(
browser
,
contract
,
callback
)
{
...
...
@@ -23,6 +23,6 @@ function testSimpleContract (browser, contract, callback) {
.
click
(
'.newFile'
)
.
clearValue
(
'#input textarea'
)
.
setValue
(
'#input textarea'
,
contract
)
.
pause
(
'5000'
)
;
contractHelper
.
checkCompiledContracts
(
browser
,
[
'test1'
,
'test2'
],
callback
)
;
.
pause
(
'5000'
)
contractHelper
.
checkCompiledContracts
(
browser
,
[
'test1'
,
'test2'
],
callback
)
}
test-browser/tests/smoke-test.js
View file @
2126391e
'use strict'
;
'use strict'
module
.
exports
=
{
'Smoke test'
:
function
(
browser
)
{
...
...
@@ -7,6 +7,6 @@ module.exports = {
.
waitForElementVisible
(
'#righthand-panel'
,
10000
)
.
pause
(
'10000'
)
.
assert
.
containsText
(
'#righthand-panel'
,
'Solidity version'
)
.
end
()
;
.
end
()
}
}
;
}
test/compiler-test.js
View file @
2126391e
'use strict'
;
'use strict'
var
test
=
require
(
'tape'
)
;
var
test
=
require
(
'tape'
)
var
Compiler
=
require
(
'../src/app/compiler'
)
;
var
EventManager
=
require
(
'../src/lib/eventManager'
)
;
var
Compiler
=
require
(
'../src/app/compiler'
)
var
EventManager
=
require
(
'../src/lib/eventManager'
)
test
(
'compiler.compile smoke'
,
function
(
t
)
{
t
.
plan
(
1
)
;
t
.
plan
(
1
)
var
noop
=
function
()
{}
;
var
getCacheFile
=
function
()
{
return
'fakeCacheFile'
;
};
var
fakeEditor
=
{
onChangeSetup
:
noop
,
clearAnnotations
:
noop
,
getValue
:
noop
,
setCacheFileContent
:
noop
,
getCacheFile
:
getCacheFile
}
;
var
fakeQueryParams
=
{
get
:
function
()
{
return
{}
;
}};
var
compiler
=
new
Compiler
(
fakeEditor
,
fakeQueryParams
,
null
,
null
,
new
EventManager
())
;
compiler
.
setCompileJSON
(
noop
)
;
compiler
.
compile
()
;
t
.
ok
(
compiler
)
;
})
;
var
noop
=
function
()
{}
var
getCacheFile
=
function
()
{
return
'fakeCacheFile'
}
var
fakeEditor
=
{
onChangeSetup
:
noop
,
clearAnnotations
:
noop
,
getValue
:
noop
,
setCacheFileContent
:
noop
,
getCacheFile
:
getCacheFile
}
var
fakeQueryParams
=
{
get
:
function
()
{
return
{}
}}
var
compiler
=
new
Compiler
(
fakeEditor
,
fakeQueryParams
,
null
,
null
,
new
EventManager
())
compiler
.
setCompileJSON
(
noop
)
compiler
.
compile
()
t
.
ok
(
compiler
)
})
test/gist-handler-test.js
View file @
2126391e
'use strict'
;
'use strict'
var
test
=
require
(
'tape'
)
;
var
test
=
require
(
'tape'
)
var
GistHandler
=
require
(
'../src/app/gist-handler'
)
;
var
GistHandler
=
require
(
'../src/app/gist-handler'
)
test
(
'gistHandler.handleLoad with no gist param'
,
function
(
t
)
{
t
.
plan
(
1
)
;
t
.
plan
(
1
)
var
gistHandler
=
new
GistHandler
({})
;
var
gistHandler
=
new
GistHandler
({})
var
params
=
{}
;
var
result
=
gistHandler
.
handleLoad
(
params
,
null
)
;
var
params
=
{}
var
result
=
gistHandler
.
handleLoad
(
params
,
null
)
t
.
equal
(
result
,
false
)
;
})
;
t
.
equal
(
result
,
false
)
})
test
(
'gistHandler.handleLoad with blank gist param, and invalid user input'
,
function
(
t
)
{
t
.
plan
(
3
)
;
t
.
plan
(
3
)
var
fakeWindow
=
{
prompt
:
function
(
message
)
{
t
.
ok
(
message
)
;
t
.
ok
(
message
.
match
(
/gist/i
))
;
return
'invalid'
;
}}
;
t
.
ok
(
message
)
t
.
ok
(
message
.
match
(
/gist/i
))
return
'invalid'
}}
var
gistHandler
=
new
GistHandler
(
fakeWindow
)
;
var
gistHandler
=
new
GistHandler
(
fakeWindow
)
var
params
=
{
'gist'
:
''
}
;
var
result
=
gistHandler
.
handleLoad
(
params
,
null
)
;
var
params
=
{
'gist'
:
''
}
var
result
=
gistHandler
.
handleLoad
(
params
,
null
)
t
.
equal
(
result
,
false
)
;
})
;
t
.
equal
(
result
,
false
)
})
test
(
'gistHandler.handleLoad with blank gist param, and valid user input'
,
function
(
t
)
{
t
.
plan
(
4
)
;
t
.
plan
(
4
)
var
fakeWindow
=
{
prompt
:
function
(
message
)
{
t
.
ok
(
message
)
;
t
.
ok
(
message
.
match
(
/gist/i
))
;
return
'Beef1234'
;
}}
;
t
.
ok
(
message
)
t
.
ok
(
message
.
match
(
/gist/i
))
return
'Beef1234'
}}
var
cb
=
function
(
gistId
)
{
t
.
equal
(
gistId
,
'Beef1234'
)
;
}
;
t
.
equal
(
gistId
,
'Beef1234'
)
}
var
gistHandler
=
new
GistHandler
(
fakeWindow
)
;
var
gistHandler
=
new
GistHandler
(
fakeWindow
)
var
params
=
{
'gist'
:
''
}
;
var
result
=
gistHandler
.
handleLoad
(
params
,
cb
)
;
var
params
=
{
'gist'
:
''
}
var
result
=
gistHandler
.
handleLoad
(
params
,
cb
)
t
.
equal
(
result
,
true
)
;
})
;
t
.
equal
(
result
,
true
)
})
test
(
'gistHandler.handleLoad with gist param'
,
function
(
t
)
{
t
.
plan
(
2
)
;
t
.
plan
(
2
)
var
gistHandler
=
new
GistHandler
({})
;
var
gistHandler
=
new
GistHandler
({})
var
params
=
{
'gist'
:
'abc'
}
;
var
params
=
{
'gist'
:
'abc'
}
var
cb
=
function
(
gistId
)
{
t
.
equal
(
gistId
,
'abc'
)
;
}
;
t
.
equal
(
gistId
,
'abc'
)
}
var
result
=
gistHandler
.
handleLoad
(
params
,
cb
);
t
.
equal
(
result
,
true
);
});
var
result
=
gistHandler
.
handleLoad
(
params
,
cb
)
t
.
equal
(
result
,
true
)
})
test/index.js
View file @
2126391e
'use strict'
;
'use strict'
require
(
'./compiler-test'
)
;
require
(
'./gist-handler-test'
)
;
require
(
'./query-params-test'
)
;
require
(
'./compiler-test'
)
require
(
'./gist-handler-test'
)
require
(
'./query-params-test'
)
test/query-params-test.js
View file @
2126391e
'use strict'
;
'use strict'
var
test
=
require
(
'tape'
)
;
var
test
=
require
(
'tape'
)
var
QueryParams
=
require
(
'../src/app/query-params'
)
;
var
QueryParams
=
require
(
'../src/app/query-params'
)
test
(
'queryParams.get'
,
function
(
t
)
{
t
.
plan
(
2
)
;
t
.
plan
(
2
)
var
fakeWindow
=
{
location
:
{
hash
:
'#wat=sup&foo=bar'
,
search
:
''
}}
;
var
params
=
new
QueryParams
(
fakeWindow
).
get
()
;
t
.
equal
(
params
.
wat
,
'sup'
)
;
t
.
equal
(
params
.
foo
,
'bar'
)
;
})
;
var
fakeWindow
=
{
location
:
{
hash
:
'#wat=sup&foo=bar'
,
search
:
''
}}
var
params
=
new
QueryParams
(
fakeWindow
).
get
()
t
.
equal
(
params
.
wat
,
'sup'
)
t
.
equal
(
params
.
foo
,
'bar'
)
})
test
(
'queryParams.update'
,
function
(
t
)
{
t
.
plan
(
1
)
;
t
.
plan
(
1
)
var
fakeWindow
=
{
location
:
{
hash
:
'#wat=sup'
,
search
:
''
}}
;
var
qp
=
new
QueryParams
(
fakeWindow
)
;
qp
.
update
({
foo
:
'bar'
})
;
t
.
equal
(
fakeWindow
.
location
.
hash
,
'#wat=sup&foo=bar'
)
;
})
;
var
fakeWindow
=
{
location
:
{
hash
:
'#wat=sup'
,
search
:
''
}}
var
qp
=
new
QueryParams
(
fakeWindow
)
qp
.
update
({
foo
:
'bar'
})
t
.
equal
(
fakeWindow
.
location
.
hash
,
'#wat=sup&foo=bar'
)
})
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