From 4d3f8e849b75b7854a22ce3f369888d3578bb9e1 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 31 May 2014 00:49:07 +0200 Subject: [PATCH] Javascript console and env.load(), env.note, ... --- alethzero/Main.ui | 274 ++++++++++++++++++++++++++++++++++++- alethzero/MainWin.cpp | 76 +++++++++- alethzero/MainWin.h | 10 ++ libethereum/Client.cpp | 2 - libethereum/Client.h | 1 + liblll/Parser.cpp | 2 +- libqethereum/QEthereum.cpp | 9 +- 7 files changed, 362 insertions(+), 12 deletions(-) diff --git a/alethzero/Main.ui b/alethzero/Main.ui index 133941a8a..8151fd61e 100644 --- a/alethzero/Main.ui +++ b/alethzero/Main.ui @@ -96,9 +96,6 @@ - - - @@ -1014,6 +1011,277 @@ + + + QDockWidget::DockWidgetFeatureMask + + + Javascript Console + + + 8 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + about:blank + + + + + + + + 0 + + + + + + 14 + 0 + + + + + + + + + 51 + 85 + 221 + + + + + + + 255 + 255 + 255 + + + + + + + 51 + 85 + 221 + + + + + + + 51 + 85 + 221 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + + + 51 + 85 + 221 + + + + + + + 255 + 255 + 255 + + + + + + + 51 + 85 + 221 + + + + + + + 51 + 85 + 221 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + + + 51 + 85 + 221 + + + + + + + 255 + 255 + 255 + + + + + + + 51 + 85 + 221 + + + + + + + 51 + 85 + 221 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + + false + + + background-color: white; +color: #35d; +font-weight: bold; +font-family: Monospace, Ubuntu Mono, Lucida Console, Courier New; +font-size: 14pt + + + > + + + 0 + + + jsInput + + + + + + + + 0 + 0 + + + + background: white; +border: 0; +font-family: Monospace, Ubuntu Mono, Lucida Console, Courier New + + + + + + + + + false + + + + + + + + &Quit diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index ac0427022..cf8144f5c 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -233,6 +233,7 @@ Main::Main(QWidget *parent) : connect(f, &QWebFrame::javaScriptWindowObjectCleared, [=](){ auto qe = new QEthereum(this, m_client.get(), owned()); qe->setup(f); + f->addToJavaScriptWindowObject("env", this, QWebFrame::QtOwnership); }); readSettings(); @@ -254,10 +255,74 @@ Main::~Main() writeSettings(); } +void Main::load(QString _s) +{ + QFile fin(_s); + if (!fin.open(QFile::ReadOnly)) + return; + QString line; + while (!fin.atEnd()) + { + QString l = QString::fromUtf8(fin.readLine()); + line.append(l); + if (line.count('"') % 2) + { + line.chop(1); + } + else if (line.endsWith("\\\n")) + line.chop(2); + else + { + ui->webView->page()->currentFrame()->evaluateJavaScript(line); + //eval(line); + line.clear(); + } + } +} +// env.load("/home/gav/eth/init.eth") + +void Main::note(QString _s) +{ + cnote << _s.toStdString(); +} + +void Main::debug(QString _s) +{ + cdebug << _s.toStdString(); +} + +void Main::warn(QString _s) +{ + cwarn << _s.toStdString(); +} + void Main::on_jsInput_returnPressed() { - ui->jsInput->setText(ui->webView->page()->currentFrame()->evaluateJavaScript(ui->jsInput->text()).toString()); - ui->jsInput->setSelection(0, ui->jsInput->text().size()); + eval(ui->jsInput->text()); + ui->jsInput->setText(""); +} + +void Main::eval(QString const& _js) +{ + if (_js.trimmed().isEmpty()) + return; + QVariant ev = ui->webView->page()->currentFrame()->evaluateJavaScript(_js); + QString s; + if (ev.isNull()) + s = "null"; + else if (ev.type() == QVariant::String) + s = "\"" + ev.toString().toHtmlEscaped() + "\""; + else if (ev.type() == QVariant::Int || ev.type() == QVariant::Double) + s = "" + ev.toString().toHtmlEscaped() + ""; + else + s = "unknown type"; + m_consoleHistory.push_back(qMakePair(_js, s)); + s = "
"; + for (auto const& i: m_consoleHistory) + s += "
>" + i.first.toHtmlEscaped() + "
" + "
 " + i.second + "
"; + s += "
"; + ui->jsConsole->setHtml(s); } QString Main::pretty(eth::Address _a) const @@ -489,14 +554,15 @@ void Main::refresh(bool _override) auto acs = st.addresses(); ui->accounts->clear(); ui->contracts->clear(); - for (auto n = 0; n < (ui->showAllAccounts->isChecked() ? 2 : 1); ++n) + for (auto n = 0; n < 2; ++n) for (auto i: acs) { auto r = render(i.first); if (r.contains('(') == !n) { - (new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(i.second).c_str()).arg(r).arg((unsigned)state().transactionsFrom(i.first)), ui->accounts)) - ->setData(Qt::UserRole, QByteArray((char const*)i.first.data(), Address::size)); + if (n == 0 || ui->showAllAccounts->isChecked()) + (new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(i.second).c_str()).arg(r).arg((unsigned)state().transactionsFrom(i.first)), ui->accounts)) + ->setData(Qt::UserRole, QByteArray((char const*)i.first.data(), Address::size)); if (st.addressHasCode(i.first)) (new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(i.second).c_str()).arg(r).arg((unsigned)st.transactionsFrom(i.first)), ui->contracts)) ->setData(Qt::UserRole, QByteArray((char const*)i.first.data(), Address::size)); diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index 2b972b73a..cc4779587 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -63,7 +63,15 @@ public: QList const& owned() const { return m_myKeys; } +public slots: + void load(QString _file); + void note(QString _entry); + void debug(QString _entry); + void warn(QString _entry); + private slots: + void eval(QString const& _js); + void on_connect_triggered(); void on_mine_triggered(); void on_send_clicked(); @@ -155,5 +163,7 @@ private: QNetworkAccessManager m_webCtrl; + QList> m_consoleHistory; + QEthereum* m_ethereum; }; diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 6f5268869..eb9ea80ad 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -154,7 +154,6 @@ void Client::transact(Secret _secret, u256 _value, Address _dest, bytes const& _ t.sign(_secret); cnote << "New transaction " << t; m_tq.attemptImport(t.rlp()); - m_changed = true; } Address Client::transact(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice) @@ -170,7 +169,6 @@ Address Client::transact(Secret _secret, u256 _endowment, bytes const& _init, u2 t.sign(_secret); cnote << "New transaction " << t; m_tq.attemptImport(t.rlp()); - m_changed = true; return right160(sha3(rlpList(t.sender(), t.nonce))); } diff --git a/libethereum/Client.h b/libethereum/Client.h index 880e2389b..0d61274a3 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -122,6 +122,7 @@ public: /// Determines whether at least one of the state/blockChain/transactionQueue has changed since the last call to changed(). bool changed() const { auto ret = m_changed; m_changed = false; return ret; } + bool peekChanged() const { return m_changed; } /// Get the object representing the current state of Ethereum. State const& state() const { return m_preMine; } diff --git a/liblll/Parser.cpp b/liblll/Parser.cpp index 10d2188a4..de0a5428a 100644 --- a/liblll/Parser.cpp +++ b/liblll/Parser.cpp @@ -75,7 +75,7 @@ void eth::parseTreeLLL(string const& _s, sp::utree& o_out) qi::rule element; qi::rule str = '"' > qi::lexeme[+(~qi::char_(std::string("\"") + '\0'))] > '"'; - qi::rule strsh = '\'' > qi::lexeme[+(~qi::char_(std::string(" ;())") + '\0'))]; + qi::rule strsh = '\'' > qi::lexeme[+(~qi::char_(std::string(" ;@()[]{}:") + '\0'))]; qi::rule symbol = qi::lexeme[+(~qi::char_(std::string(" @[]{}:();\"\x01-\x1f\x7f") + '\0'))]; qi::rule intstr = qi::lexeme[ qi::no_case["0x"][qi::_val = "0x"] >> *qi::char_("0-9a-fA-F")[qi::_val += qi::_1]] | qi::lexeme[+qi::char_("0-9")[qi::_val += qi::_1]]; qi::rule integer = intstr; diff --git a/libqethereum/QEthereum.cpp b/libqethereum/QEthereum.cpp index 8b17861fe..02d62c5b9 100644 --- a/libqethereum/QEthereum.cpp +++ b/libqethereum/QEthereum.cpp @@ -394,12 +394,19 @@ unsigned QEthereum::peerCount() const QString QEthereum::doCreate(QString _secret, QString _amount, QString _init, QString _gas, QString _gasPrice) { - return toQJS(client()->transact(toSecret(_secret), toU256(_amount), toBytes(_init), toU256(_gas), toU256(_gasPrice))); + client()->changed(); + auto ret = toQJS(client()->transact(toSecret(_secret), toU256(_amount), toBytes(_init), toU256(_gas), toU256(_gasPrice))); + while (!client()->peekChanged()) + usleep(10000); + return ret; } void QEthereum::doTransact(QString _secret, QString _amount, QString _dest, QString _data, QString _gas, QString _gasPrice) { + client()->changed(); client()->transact(toSecret(_secret), toU256(_amount), toAddress(_dest), toBytes(_data), toU256(_gas), toU256(_gasPrice)); + while (!client()->peekChanged()) + usleep(10000); } // extra bits needed to link on VS