Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -512,3 +512,4 @@ a license to everyone to use it as detailed in LICENSE.)
* Marat Dukhan <maratek@google.com> (copyright owned by Google, LLC)
* Stephan Reiter <reste@google.com> (copyright owned by Google, LLC)
* kamenokonyokonyoko <kamenokonokotan@gmail.com>
* Lectem <lectem@gmail.com>
18 changes: 13 additions & 5 deletions site/source/docs/api_reference/val.h.rst
Original file line number Diff line number Diff line change
Expand Up @@ -246,14 +246,22 @@ Guide material for this class can be found in :ref:`embind-val-guide`.
:returns: **HamishW**-Replace with description.


.. cpp:function:: std::vector<T> vecFromJSArray(val v)
.. cpp:function:: std::vector<T> vecFromJSArray(const val& v)

**HamishW**-Replace with description.
Copies a javascript array into a std::vector, checking the type of each element.
For a more efficient but unsafe version working with numbers, see convertJSObjectToNumberVector.

**HamishW**. I believe NOT internal. Please confirm.
:param val v: The javascript array to be copied
:returns: A std::vector<T> made from the javascript array

:param val v: **HamishW**-Replace with description.
:returns: **HamishW**-Replace with description.
.. cpp:function:: std::vector<T> convertJSArrayToNumberVector(const val& v)

Converts a javascript object into a std::vector<T> efficiently, as if using the javascript `Number()` function on each element.
This is way more efficient than vecFromJSArray on any array with more than 2 values, but is less safe.
No type checking is done, so any invalid array entry will silently be replaced by a NaN value (or 0 for interger types).

:param val v: The javascript (typed) array to be copied
:returns: A std::vector<T> made from the javascript array


.. cpp:function:: val await() const
Expand Down
28 changes: 23 additions & 5 deletions system/include/emscripten/val.h
Original file line number Diff line number Diff line change
Expand Up @@ -580,15 +580,33 @@ namespace emscripten {
};
}

template<typename T>
std::vector<T> vecFromJSArray(val v) {
auto l = v["length"].as<unsigned>();
template <typename T>
std::vector<T> vecFromJSArray(const val& v) {
const size_t l = v["length"].as<size_t>();

std::vector<T> rv;
for(unsigned i = 0; i < l; ++i) {
rv.reserve(l);
for (size_t i = 0; i < l; ++i) {
rv.push_back(v[i].as<T>());
}

return rv;
};
}

template <typename T>
std::vector<T> convertJSArrayToNumberVector(const val& v) {
const size_t l = v["length"].as<size_t>();

std::vector<T> rv;
rv.resize(l);

// Copy the array into our vector through the use of typed arrays.
// It will try to convert each element through Number().
// See https://www.ecma-international.org/ecma-262/6.0/#sec-%typedarray%.prototype.set-array-offset
// and https://www.ecma-international.org/ecma-262/6.0/#sec-tonumber
val memoryView{ typed_memory_view(l, rv.data()) };
memoryView.call<void>("set", v);

return rv;
}
}
33 changes: 28 additions & 5 deletions tests/embind/test_val.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <stdio.h>
#include <iostream>
#include <cmath>
#include <emscripten/bind.h>
#include <emscripten/emscripten.h>
#include <emscripten/val.h>
Expand Down Expand Up @@ -570,19 +571,41 @@ int main()
ensure_js("test_val_throw_(new TypeError('message'))");

// this test should probably go elsewhere as it is not a member of val
test("template<typename T> std::vector<T> vecFromJSArray(val v)");
test("template<typename T> std::vector<T> vecFromJSArray(const val& v)");
EM_ASM(
// can't declare like this because i get:
// error: expected ')'
// possibly a bug with EM_ASM
//a = [1, '2'];
a = [];
a[0] = 1;
a[1] = 'b';
a[1] = '42';
a[2] = 'b';
a[3] = new Date(100000);
);
ensure(vecFromJSArray<val>(val::global("a")).at(0).as<int>() == 1);
ensure(vecFromJSArray<val>(val::global("a")).at(1).as<string>() == "b");
ensure(vecFromJSArray<val>(val::global("a")).size() == 2);
const std::vector<val>& aAsArray = vecFromJSArray<val>(val::global("a"));
ensure(aAsArray.at(0).as<int>() == 1);
ensure(aAsArray.at(1).as<string>() == "42");
ensure(aAsArray.at(2).as<string>() == "b");
ensure(aAsArray.size() == 4);

test("template<typename T> std::vector<T> convertJSArrayToNumberVector(const val& v)");

const std::vector<float>& aAsNumberVectorFloat = convertJSArrayToNumberVector<float>(val::global("a"));
ensure(aAsNumberVectorFloat.size() == 4);

ensure(aAsNumberVectorFloat.at(0) == 1.f);
ensure(aAsNumberVectorFloat.at(1) == 42.f); // String containing numbers are converted correctly
ensure(std::isnan(aAsNumberVectorFloat.at(2))); // NaN returned if can not be converted for floats
ensure(aAsNumberVectorFloat.at(3) == 100000.f); // Date returns milliseconds since epoch

const std::vector<uint32_t>& aAsNumberVectorUint32_t = convertJSArrayToNumberVector<uint32_t>(val::global("a"));
ensure(aAsNumberVectorUint32_t.size() == 4);

ensure(aAsNumberVectorUint32_t.at(0) == 1);
ensure(aAsNumberVectorUint32_t.at(1) == 42); // String containing numbers are converted correctly
ensure(aAsNumberVectorUint32_t.at(2) == 0); // 0 is returned if can not be converted for integers
ensure(aAsNumberVectorUint32_t.at(3) == 100000); // Date returns milliseconds since epoch

printf("end\n");
return 0;
Expand Down
15 changes: 14 additions & 1 deletion tests/embind/test_val.out
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,20 @@ pass
pass
pass
test:
template<typename T> std::vector<T> vecFromJSArray(val v)
template<typename T> std::vector<T> vecFromJSArray(const val& v)
pass
pass
pass
pass
test:
template<typename T> std::vector<T> convertJSArrayToNumberVector(const val& v)
pass
pass
pass
pass
pass
pass
pass
pass
pass
pass
Expand Down