@@ -25,7 +25,6 @@ using v8::ConstructorBehavior; |
25 | 25 | using v8::Context; |
26 | 26 | using v8::DontDelete; |
27 | 27 | using v8::Exception; |
28 | | -using v8::External; |
29 | 28 | using v8::Function; |
30 | 29 | using v8::FunctionCallback; |
31 | 30 | using v8::FunctionCallbackInfo; |
@@ -1620,142 +1619,12 @@ void StatementSync::All(const FunctionCallbackInfo<Value>& args) { |
1620 | 1619 | args.GetReturnValue().Set(Array::New(isolate, rows.data(), rows.size())); |
1621 | 1620 | } |
1622 | 1621 |
|
1623 | | -void StatementSync::IterateReturnCallback( |
1624 | | - const FunctionCallbackInfo<Value>& args) { |
1625 | | - Environment* env = Environment::GetCurrent(args); |
1626 | | - auto isolate = env->isolate(); |
1627 | | - auto context = isolate->GetCurrentContext(); |
1628 | | - |
1629 | | - auto self = args.This(); |
1630 | | - // iterator has fetch all result or break, prevent next func to return result |
1631 | | - if (self->Set(context, env->isfinished_string(), Boolean::New(isolate, true)) |
1632 | | - .IsNothing()) { |
1633 | | - // An error will have been scheduled. |
1634 | | - return; |
1635 | | - } |
1636 | | - |
1637 | | - Local<Value> val; |
1638 | | - if (!self->Get(context, env->statement_string()).ToLocal(&val)) { |
1639 | | - // An error will have been scheduled. |
1640 | | - return; |
1641 | | - } |
1642 | | - auto external_stmt = Local<External>::Cast(val); |
1643 | | - auto stmt = static_cast<StatementSync*>(external_stmt->Value()); |
1644 | | - if (!stmt->IsFinalized()) { |
1645 | | - sqlite3_reset(stmt->statement_); |
1646 | | - } |
1647 | | - |
1648 | | - LocalVector<Name> keys(isolate, {env->done_string(), env->value_string()}); |
1649 | | - LocalVector<Value> values(isolate, |
1650 | | - {Boolean::New(isolate, true), Null(isolate)}); |
1651 | | - |
1652 | | - DCHECK_EQ(keys.size(), values.size()); |
1653 | | - Local<Object> result = Object::New( |
1654 | | - isolate, Null(isolate), keys.data(), values.data(), keys.size()); |
1655 | | - args.GetReturnValue().Set(result); |
1656 | | -} |
1657 | | - |
1658 | | -void StatementSync::IterateNextCallback( |
1659 | | - const FunctionCallbackInfo<Value>& args) { |
1660 | | - Environment* env = Environment::GetCurrent(args); |
1661 | | - auto isolate = env->isolate(); |
1662 | | - auto context = isolate->GetCurrentContext(); |
1663 | | - |
1664 | | - auto self = args.This(); |
1665 | | - |
1666 | | - Local<Value> val; |
1667 | | - if (!self->Get(context, env->isfinished_string()).ToLocal(&val)) { |
1668 | | - // An error will have been scheduled. |
1669 | | - return; |
1670 | | - } |
1671 | | - |
1672 | | - // skip iteration if is_finished |
1673 | | - auto is_finished = Local<Boolean>::Cast(val); |
1674 | | - if (is_finished->Value()) { |
1675 | | - Local<Name> keys[] = {env->done_string(), env->value_string()}; |
1676 | | - Local<Value> values[] = {Boolean::New(isolate, true), Null(isolate)}; |
1677 | | - static_assert(arraysize(keys) == arraysize(values)); |
1678 | | - Local<Object> result = Object::New( |
1679 | | - isolate, Null(isolate), &keys[0], &values[0], arraysize(keys)); |
1680 | | - args.GetReturnValue().Set(result); |
1681 | | - return; |
1682 | | - } |
1683 | | - |
1684 | | - if (!self->Get(context, env->statement_string()).ToLocal(&val)) { |
1685 | | - // An error will have been scheduled. |
1686 | | - return; |
1687 | | - } |
1688 | | - |
1689 | | - auto external_stmt = Local<External>::Cast(val); |
1690 | | - auto stmt = static_cast<StatementSync*>(external_stmt->Value()); |
1691 | | - |
1692 | | - if (!self->Get(context, env->num_cols_string()).ToLocal(&val)) { |
1693 | | - // An error will have been scheduled. |
1694 | | - return; |
1695 | | - } |
1696 | | - |
1697 | | - auto num_cols = Local<Integer>::Cast(val)->Value(); |
1698 | | - |
1699 | | - THROW_AND_RETURN_ON_BAD_STATE( |
1700 | | - env, stmt->IsFinalized(), "statement has been finalized"); |
1701 | | - |
1702 | | - int r = sqlite3_step(stmt->statement_); |
1703 | | - if (r != SQLITE_ROW) { |
1704 | | - CHECK_ERROR_OR_THROW( |
1705 | | - env->isolate(), stmt->db_.get(), r, SQLITE_DONE, void()); |
1706 | | - |
1707 | | - // cleanup when no more rows to fetch |
1708 | | - sqlite3_reset(stmt->statement_); |
1709 | | - if (self->Set( |
1710 | | - context, env->isfinished_string(), Boolean::New(isolate, true)) |
1711 | | - .IsNothing()) { |
1712 | | - // An error would have been scheduled |
1713 | | - return; |
1714 | | - } |
1715 | | - |
1716 | | - LocalVector<Name> keys(isolate, {env->done_string(), env->value_string()}); |
1717 | | - LocalVector<Value> values(isolate, |
1718 | | - {Boolean::New(isolate, true), Null(isolate)}); |
1719 | | - |
1720 | | - DCHECK_EQ(keys.size(), values.size()); |
1721 | | - Local<Object> result = Object::New( |
1722 | | - isolate, Null(isolate), keys.data(), values.data(), keys.size()); |
1723 | | - args.GetReturnValue().Set(result); |
1724 | | - return; |
1725 | | - } |
1726 | | - |
1727 | | - LocalVector<Name> row_keys(isolate); |
1728 | | - row_keys.reserve(num_cols); |
1729 | | - LocalVector<Value> row_values(isolate); |
1730 | | - row_values.reserve(num_cols); |
1731 | | - for (int i = 0; i < num_cols; ++i) { |
1732 | | - Local<Name> key; |
1733 | | - if (!stmt->ColumnNameToName(i).ToLocal(&key)) return; |
1734 | | - Local<Value> val; |
1735 | | - if (!stmt->ColumnToValue(i).ToLocal(&val)) return; |
1736 | | - row_keys.emplace_back(key); |
1737 | | - row_values.emplace_back(val); |
1738 | | - } |
1739 | | - |
1740 | | - Local<Object> row = Object::New( |
1741 | | - isolate, Null(isolate), row_keys.data(), row_values.data(), num_cols); |
1742 | | - |
1743 | | - LocalVector<Name> keys(isolate, {env->done_string(), env->value_string()}); |
1744 | | - LocalVector<Value> values(isolate, {Boolean::New(isolate, false), row}); |
1745 | | - |
1746 | | - DCHECK_EQ(keys.size(), values.size()); |
1747 | | - Local<Object> result = Object::New( |
1748 | | - isolate, Null(isolate), keys.data(), values.data(), keys.size()); |
1749 | | - args.GetReturnValue().Set(result); |
1750 | | -} |
1751 | | - |
1752 | 1622 | void StatementSync::Iterate(const FunctionCallbackInfo<Value>& args) { |
1753 | 1623 | StatementSync* stmt; |
1754 | 1624 | ASSIGN_OR_RETURN_UNWRAP(&stmt, args.This()); |
1755 | 1625 | Environment* env = Environment::GetCurrent(args); |
1756 | 1626 | THROW_AND_RETURN_ON_BAD_STATE( |
1757 | 1627 | env, stmt->IsFinalized(), "statement has been finalized"); |
1758 | | - auto isolate = env->isolate(); |
1759 | 1628 | auto context = env->context(); |
1760 | 1629 | int r = sqlite3_reset(stmt->statement_); |
1761 | 1630 | CHECK_ERROR_OR_THROW(env->isolate(), stmt->db_.get(), r, SQLITE_OK, void()); |
@@ -1764,67 +1633,28 @@ void StatementSync::Iterate(const FunctionCallbackInfo<Value>& args) { |
1764 | 1633 | return; |
1765 | 1634 | } |
1766 | 1635 |
|
1767 | | - Local<Function> next_func; |
1768 | | - Local<Function> return_func; |
1769 | | - if (!Function::New(context, StatementSync::IterateNextCallback) |
1770 | | - .ToLocal(&next_func) || |
1771 | | - !Function::New(context, StatementSync::IterateReturnCallback) |
1772 | | - .ToLocal(&return_func)) { |
1773 | | - // An error will have been scheduled. |
1774 | | - return; |
1775 | | - } |
1776 | | - |
1777 | | - Local<Name> keys[] = {env->next_string(), env->return_string()}; |
1778 | | - Local<Value> values[] = {next_func, return_func}; |
1779 | | - static_assert(arraysize(keys) == arraysize(values)); |
1780 | | - |
1781 | 1636 | Local<Object> global = context->Global(); |
1782 | 1637 | Local<Value> js_iterator; |
1783 | 1638 | Local<Value> js_iterator_prototype; |
1784 | | - if (!global->Get(context, env->iterator_string()).ToLocal(&js_iterator)) |
| 1639 | + if (!global->Get(context, env->iterator_string()).ToLocal(&js_iterator)) { |
1785 | 1640 | return; |
| 1641 | + } |
1786 | 1642 | if (!js_iterator.As<Object>() |
1787 | 1643 | ->Get(context, env->prototype_string()) |
1788 | | - .ToLocal(&js_iterator_prototype)) |
1789 | | - return; |
1790 | | - |
1791 | | - Local<Object> iterable_iterator = Object::New( |
1792 | | - isolate, js_iterator_prototype, &keys[0], &values[0], arraysize(keys)); |
1793 | | - |
1794 | | - auto num_cols_pd = v8::PropertyDescriptor( |
1795 | | - v8::Integer::New(isolate, sqlite3_column_count(stmt->statement_)), false); |
1796 | | - num_cols_pd.set_enumerable(false); |
1797 | | - num_cols_pd.set_configurable(false); |
1798 | | - if (iterable_iterator |
1799 | | - ->DefineProperty(context, env->num_cols_string(), num_cols_pd) |
1800 | | - .IsNothing()) { |
1801 | | - // An error will have been scheduled. |
| 1644 | + .ToLocal(&js_iterator_prototype)) { |
1802 | 1645 | return; |
1803 | 1646 | } |
1804 | 1647 |
|
1805 | | - auto stmt_pd = |
1806 | | - v8::PropertyDescriptor(v8::External::New(isolate, stmt), false); |
1807 | | - stmt_pd.set_enumerable(false); |
1808 | | - stmt_pd.set_configurable(false); |
1809 | | - if (iterable_iterator |
1810 | | - ->DefineProperty(context, env->statement_string(), stmt_pd) |
| 1648 | + BaseObjectPtr<StatementSyncIterator> iter = |
| 1649 | + StatementSyncIterator::Create(env, BaseObjectPtr<StatementSync>(stmt)); |
| 1650 | + if (iter->object() |
| 1651 | + ->GetPrototype() |
| 1652 | + .As<Object>() |
| 1653 | + ->SetPrototype(context, js_iterator_prototype) |
1811 | 1654 | .IsNothing()) { |
1812 | | - // An error will have been scheduled. |
1813 | 1655 | return; |
1814 | 1656 | } |
1815 | | - |
1816 | | - auto is_finished_pd = |
1817 | | - v8::PropertyDescriptor(v8::Boolean::New(isolate, false), true); |
1818 | | - stmt_pd.set_enumerable(false); |
1819 | | - stmt_pd.set_configurable(false); |
1820 | | - if (iterable_iterator |
1821 | | - ->DefineProperty(context, env->isfinished_string(), is_finished_pd) |
1822 | | - .IsNothing()) { |
1823 | | - // An error will have been scheduled. |
1824 | | - return; |
1825 | | - } |
1826 | | - |
1827 | | - args.GetReturnValue().Set(iterable_iterator); |
| 1657 | + args.GetReturnValue().Set(iter->object()); |
1828 | 1658 | } |
1829 | 1659 |
|
1830 | 1660 | void StatementSync::Get(const FunctionCallbackInfo<Value>& args) { |
@@ -2144,6 +1974,118 @@ BaseObjectPtr<StatementSync> StatementSync::Create( |
2144 | 1974 | return MakeBaseObject<StatementSync>(env, obj, std::move(db), stmt); |
2145 | 1975 | } |
2146 | 1976 |
|
| 1977 | +StatementSyncIterator::StatementSyncIterator(Environment* env, |
| 1978 | + Local<Object> object, |
| 1979 | + BaseObjectPtr<StatementSync> stmt) |
| 1980 | + : BaseObject(env, object), stmt_(std::move(stmt)) { |
| 1981 | + MakeWeak(); |
| 1982 | + done_ = false; |
| 1983 | +} |
| 1984 | + |
| 1985 | +StatementSyncIterator::~StatementSyncIterator() {} |
| 1986 | +void StatementSyncIterator::MemoryInfo(MemoryTracker* tracker) const {} |
| 1987 | + |
| 1988 | +Local<FunctionTemplate> StatementSyncIterator::GetConstructorTemplate( |
| 1989 | + Environment* env) { |
| 1990 | + Local<FunctionTemplate> tmpl = |
| 1991 | + env->sqlite_statement_sync_iterator_constructor_template(); |
| 1992 | + if (tmpl.IsEmpty()) { |
| 1993 | + Isolate* isolate = env->isolate(); |
| 1994 | + tmpl = NewFunctionTemplate(isolate, IllegalConstructor); |
| 1995 | + tmpl->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "StatementSyncIterator")); |
| 1996 | + tmpl->InstanceTemplate()->SetInternalFieldCount( |
| 1997 | + StatementSync::kInternalFieldCount); |
| 1998 | + SetProtoMethod(isolate, tmpl, "next", StatementSyncIterator::Next); |
| 1999 | + SetProtoMethod(isolate, tmpl, "return", StatementSyncIterator::Return); |
| 2000 | + env->set_sqlite_statement_sync_iterator_constructor_template(tmpl); |
| 2001 | + } |
| 2002 | + return tmpl; |
| 2003 | +} |
| 2004 | + |
| 2005 | +BaseObjectPtr<StatementSyncIterator> StatementSyncIterator::Create( |
| 2006 | + Environment* env, BaseObjectPtr<StatementSync> stmt) { |
| 2007 | + Local<Object> obj; |
| 2008 | + if (!GetConstructorTemplate(env) |
| 2009 | + ->InstanceTemplate() |
| 2010 | + ->NewInstance(env->context()) |
| 2011 | + .ToLocal(&obj)) { |
| 2012 | + return BaseObjectPtr<StatementSyncIterator>(); |
| 2013 | + } |
| 2014 | + |
| 2015 | + return MakeBaseObject<StatementSyncIterator>(env, obj, std::move(stmt)); |
| 2016 | +} |
| 2017 | + |
| 2018 | +void StatementSyncIterator::Next(const FunctionCallbackInfo<Value>& args) { |
| 2019 | + StatementSyncIterator* iter; |
| 2020 | + ASSIGN_OR_RETURN_UNWRAP(&iter, args.This()); |
| 2021 | + Environment* env = Environment::GetCurrent(args); |
| 2022 | + THROW_AND_RETURN_ON_BAD_STATE( |
| 2023 | + env, iter->stmt_->IsFinalized(), "statement has been finalized"); |
| 2024 | + Isolate* isolate = env->isolate(); |
| 2025 | + LocalVector<Name> keys(isolate, {env->done_string(), env->value_string()}); |
| 2026 | + |
| 2027 | + if (iter->done_) { |
| 2028 | + LocalVector<Value> values(isolate, |
| 2029 | + {Boolean::New(isolate, true), Null(isolate)}); |
| 2030 | + Local<Object> result = Object::New( |
| 2031 | + isolate, Null(isolate), keys.data(), values.data(), keys.size()); |
| 2032 | + args.GetReturnValue().Set(result); |
| 2033 | + return; |
| 2034 | + } |
| 2035 | + |
| 2036 | + int r = sqlite3_step(iter->stmt_->statement_); |
| 2037 | + if (r != SQLITE_ROW) { |
| 2038 | + CHECK_ERROR_OR_THROW( |
| 2039 | + env->isolate(), iter->stmt_->db_.get(), r, SQLITE_DONE, void()); |
| 2040 | + sqlite3_reset(iter->stmt_->statement_); |
| 2041 | + LocalVector<Value> values(isolate, |
| 2042 | + {Boolean::New(isolate, true), Null(isolate)}); |
| 2043 | + Local<Object> result = Object::New( |
| 2044 | + isolate, Null(isolate), keys.data(), values.data(), keys.size()); |
| 2045 | + args.GetReturnValue().Set(result); |
| 2046 | + return; |
| 2047 | + } |
| 2048 | + |
| 2049 | + int num_cols = sqlite3_column_count(iter->stmt_->statement_); |
| 2050 | + LocalVector<Name> row_keys(isolate); |
| 2051 | + LocalVector<Value> row_values(isolate); |
| 2052 | + row_keys.reserve(num_cols); |
| 2053 | + row_values.reserve(num_cols); |
| 2054 | + for (int i = 0; i < num_cols; ++i) { |
| 2055 | + Local<Name> key; |
| 2056 | + if (!iter->stmt_->ColumnNameToName(i).ToLocal(&key)) return; |
| 2057 | + Local<Value> val; |
| 2058 | + if (!iter->stmt_->ColumnToValue(i).ToLocal(&val)) return; |
| 2059 | + row_keys.emplace_back(key); |
| 2060 | + row_values.emplace_back(val); |
| 2061 | + } |
| 2062 | + |
| 2063 | + Local<Object> row = Object::New( |
| 2064 | + isolate, Null(isolate), row_keys.data(), row_values.data(), num_cols); |
| 2065 | + LocalVector<Value> values(isolate, {Boolean::New(isolate, false), row}); |
| 2066 | + Local<Object> result = Object::New( |
| 2067 | + isolate, Null(isolate), keys.data(), values.data(), keys.size()); |
| 2068 | + args.GetReturnValue().Set(result); |
| 2069 | +} |
| 2070 | + |
| 2071 | +void StatementSyncIterator::Return(const FunctionCallbackInfo<Value>& args) { |
| 2072 | + StatementSyncIterator* iter; |
| 2073 | + ASSIGN_OR_RETURN_UNWRAP(&iter, args.This()); |
| 2074 | + Environment* env = Environment::GetCurrent(args); |
| 2075 | + THROW_AND_RETURN_ON_BAD_STATE( |
| 2076 | + env, iter->stmt_->IsFinalized(), "statement has been finalized"); |
| 2077 | + Isolate* isolate = env->isolate(); |
| 2078 | + |
| 2079 | + sqlite3_reset(iter->stmt_->statement_); |
| 2080 | + iter->done_ = true; |
| 2081 | + LocalVector<Name> keys(isolate, {env->done_string(), env->value_string()}); |
| 2082 | + LocalVector<Value> values(isolate, |
| 2083 | + {Boolean::New(isolate, true), Null(isolate)}); |
| 2084 | + Local<Object> result = Object::New( |
| 2085 | + isolate, Null(isolate), keys.data(), values.data(), keys.size()); |
| 2086 | + args.GetReturnValue().Set(result); |
| 2087 | +} |
| 2088 | + |
2147 | 2089 | Session::Session(Environment* env, |
2148 | 2090 | Local<Object> object, |
2149 | 2091 | BaseObjectWeakPtr<DatabaseSync> database, |
|