Skip to content
This repository was archived by the owner on Dec 15, 2022. It is now read-only.

Commit 6ff35dc

Browse files
committed
Adds asm.js support
1 parent b9b7a06 commit 6ff35dc

22 files changed

+645
-47
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ node_modules
22
build
33
.DS_Store
44
.clang_complete
5+
6+
/browser.js

index.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1-
try {
2-
module.exports = require('./build/Release/superstring.node')
3-
} catch (e) {
4-
module.exports = require('./build/Debug/superstring.node')
1+
if (process.env.FORCE_BROWSER_FALLBACK) {
2+
module.exports = require('./browser');
3+
} else {
4+
try {
5+
module.exports = require('./build/Release/superstring.node')
6+
} catch (e) {
7+
module.exports = require('./build/Debug/superstring.node')
8+
}
59
}

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
"name": "superstring",
33
"version": "1.0.5",
44
"description": "A data structure to efficiently represent the results of applying patches.",
5+
"main": "./index",
6+
"browser": "./browser",
57
"scripts": {
8+
"build:browser": "em++ --bind -o browser.js -O3 -std=c++14 -I src/bindings/em -I src/core -include iostream src/core/*.cc src/bindings/em/*.cc -s TOTAL_MEMORY=134217728 --memory-init-file 0",
69
"test-native": "script/test-native.js",
710
"test": "mocha test/js/*.js",
811
"benchmark": "node benchmark/marker-index.benchmark.js",

src/bindings/buffer-offset-index-wrapper.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "buffer-offset-index-wrapper.h"
2+
#include "noop.h"
23
#include "point-wrapper.h"
34

45
using namespace v8;
@@ -8,6 +9,7 @@ void BufferOffsetIndexWrapper::init(Local<Object> exports) {
89
constructor_template->SetClassName(Nan::New<String>("BufferOffsetIndex").ToLocalChecked());
910
constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
1011
const auto &prototype_template = constructor_template->PrototypeTemplate();
12+
prototype_template->Set(Nan::New<String>("delete").ToLocalChecked(), Nan::New<FunctionTemplate>(noop));
1113
prototype_template->Set(Nan::New<String>("splice").ToLocalChecked(), Nan::New<FunctionTemplate>(splice));
1214
prototype_template->Set(Nan::New<String>("position_for_character_index").ToLocalChecked(), Nan::New<FunctionTemplate>(position_for_character_index));
1315
prototype_template->Set(Nan::New<String>("character_index_for_position").ToLocalChecked(), Nan::New<FunctionTemplate>(character_index_for_position));

src/bindings/em/auto-wrap.h

Lines changed: 348 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,348 @@
1+
#pragma once
2+
3+
#include <memory>
4+
#include <type_traits>
5+
#include <unordered_map>
6+
#include <vector>
7+
8+
#include <emscripten/val.h>
9+
10+
#include "flat_set.h"
11+
#include "marker-index.h"
12+
#include "optional.h"
13+
#include "point-wrapper.h"
14+
#include "point.h"
15+
#include "text.h"
16+
17+
/********** **********/
18+
19+
template <typename LocalTypeTpl, typename WireTypeTpl>
20+
struct em_wrap_type_base {
21+
22+
using LocalType = LocalTypeTpl;
23+
using WireType = WireTypeTpl;
24+
25+
};
26+
27+
template <typename LocalType, typename WireType>
28+
struct em_wrap_type_simple : public em_wrap_type_base<LocalType, WireType> {
29+
30+
static LocalType receive(WireType data) { return data; }
31+
static WireType transmit(LocalType data) { return data; }
32+
33+
};
34+
35+
/********** **********/
36+
37+
template <typename LocalType>
38+
struct em_wrap_type : public em_wrap_type_simple<LocalType, LocalType> {};
39+
40+
/********** **********/
41+
42+
template <typename LocalType>
43+
LocalType em_receive(typename em_wrap_type<typename std::decay<LocalType>::type>::WireType data)
44+
{
45+
return em_wrap_type<typename std::decay<LocalType>::type>::receive(data);
46+
}
47+
48+
template <typename LocalType>
49+
typename em_wrap_type<typename std::decay<LocalType>::type>::WireType em_transmit(LocalType data)
50+
{
51+
return em_wrap_type<typename std::decay<LocalType>::type>::transmit(data);
52+
}
53+
54+
/********** **********/
55+
56+
template <>
57+
struct em_wrap_type<void> : public em_wrap_type_base<void, void> {};
58+
59+
template <>
60+
struct em_wrap_type<Point> : public em_wrap_type_simple<Point, PointWrapper> {};
61+
62+
template <typename ValueType>
63+
struct em_wrap_type<std::vector<ValueType>> : public em_wrap_type_base<std::vector<ValueType>, emscripten::val> {
64+
65+
static std::vector<ValueType> receive(emscripten::val const & val)
66+
{
67+
std::vector<ValueType> vec;
68+
69+
for (auto t = 0u, T = val["length"].as<unsigned>(); t < T; ++t)
70+
vec.push_back(val[t].as<ValueType>());
71+
72+
return vec;
73+
}
74+
75+
static emscripten::val transmit(std::vector<ValueType> const & vec)
76+
{
77+
auto array = emscripten::val::array();
78+
79+
for (auto const & t : vec)
80+
array.call<void>("push", em_transmit(t));
81+
82+
return array;
83+
}
84+
85+
};
86+
87+
template <typename ValueType>
88+
struct em_wrap_type<optional<ValueType>> : public em_wrap_type_base<optional<ValueType>, emscripten::val> {
89+
90+
static optional<ValueType> receive(emscripten::val const & val)
91+
{
92+
if (!val.as<bool>())
93+
return optional<ValueType>();
94+
95+
return optional<ValueType>(val.as<ValueType>());
96+
}
97+
98+
static emscripten::val transmit(optional<ValueType> const & opt)
99+
{
100+
if (!opt)
101+
return emscripten::val::undefined();
102+
103+
return emscripten::val(em_transmit(*opt));
104+
}
105+
106+
};
107+
108+
template <typename KeyType, typename ValueType>
109+
struct em_wrap_type<std::unordered_map<KeyType, ValueType>> : public em_wrap_type_base<std::unordered_map<KeyType, ValueType>, emscripten::val> {
110+
111+
static std::unordered_map<KeyType, ValueType> receive(emscripten::val const & val)
112+
{
113+
throw std::runtime_error("Unimplemented");
114+
}
115+
116+
static emscripten::val transmit(std::unordered_map<KeyType, ValueType> const & map)
117+
{
118+
auto object = emscripten::val::object();
119+
120+
for (auto const & t : map)
121+
object.set(em_transmit(t.first), em_transmit(t.second));
122+
123+
return object;
124+
}
125+
126+
};
127+
128+
template <typename ValueType>
129+
struct em_wrap_type<flat_set<ValueType>> : public em_wrap_type_base<flat_set<ValueType>, emscripten::val> {
130+
131+
static flat_set<ValueType> receive(emscripten::val const & val)
132+
{
133+
throw std::runtime_error("Unimplemented");
134+
}
135+
136+
static emscripten::val transmit(flat_set<ValueType> const & set)
137+
{
138+
auto object = emscripten::val::global("Set").new_();
139+
140+
for (auto const & t : set)
141+
object.call<void>("add", em_transmit(t));
142+
143+
return object;
144+
}
145+
146+
};
147+
148+
template <>
149+
struct em_wrap_type<MarkerIndex::SpliceResult> : public em_wrap_type_base<MarkerIndex::SpliceResult, emscripten::val> {
150+
151+
static MarkerIndex::SpliceResult receive(emscripten::val const & val)
152+
{
153+
throw std::runtime_error("Unimplemented");
154+
}
155+
156+
static emscripten::val transmit(MarkerIndex::SpliceResult const & spliceResult)
157+
{
158+
auto object = emscripten::val::object();
159+
160+
object.set("touch", em_transmit(spliceResult.touch));
161+
object.set("inside", em_transmit(spliceResult.inside));
162+
object.set("overlap", em_transmit(spliceResult.overlap));
163+
object.set("surround", em_transmit(spliceResult.surround));
164+
165+
return object;
166+
}
167+
168+
};
169+
170+
template <>
171+
struct em_wrap_type<Text> : public em_wrap_type_base<Text, std::string> {
172+
173+
static Text receive(std::string const & str)
174+
{
175+
return Text(str.begin(), str.end());
176+
}
177+
178+
static std::string transmit(Text const & text)
179+
{
180+
return std::string(text.begin(), text.end());
181+
}
182+
183+
};
184+
185+
template <>
186+
struct em_wrap_type<std::unique_ptr<Text>> : public em_wrap_type_base<std::unique_ptr<Text>, emscripten::val> {
187+
188+
static std::unique_ptr<Text> receive(emscripten::val const & val)
189+
{
190+
return std::make_unique<Text>(em_wrap_type<Text>::receive(val.as<std::string>()));
191+
}
192+
193+
static emscripten::val transmit(std::unique_ptr<Text> const & text)
194+
{
195+
if (!text)
196+
return emscripten::val::undefined();
197+
198+
return emscripten::val(em_wrap_type<Text>::transmit(*text));
199+
}
200+
201+
};
202+
203+
template <>
204+
struct em_wrap_type<Text *> : public em_wrap_type_base<Text *, emscripten::val> {
205+
206+
static Text * receive(emscripten::val const & val)
207+
{
208+
return new Text(em_wrap_type<Text>::receive(val.as<std::string>()));
209+
}
210+
211+
static emscripten::val transmit(Text * text)
212+
{
213+
if (!text)
214+
return emscripten::val::undefined();
215+
216+
return emscripten::val(em_wrap_type<Text>::transmit(*text));
217+
}
218+
219+
};
220+
221+
/********** **********/
222+
223+
template <typename T, T>
224+
struct em_wrap_fn;
225+
226+
template <typename T, typename ... Args, void (T::*fn)(Args ...)>
227+
struct em_wrap_fn<void (T::*)(Args ...), fn>
228+
{
229+
static void wrap(T & t, typename em_wrap_type<typename std::decay<Args>::type>::WireType ... args)
230+
{
231+
return (t.*fn)(em_wrap_type<typename std::decay<Args>::type>::receive(args) ...);
232+
}
233+
};
234+
235+
template <typename T, typename ... Args, void (T::*fn)(Args ...) const>
236+
struct em_wrap_fn<void (T::*)(Args ...) const, fn>
237+
{
238+
static void wrap(T const & t, typename em_wrap_type<typename std::decay<Args>::type>::WireType ... args)
239+
{
240+
return (t.*fn)(em_wrap_type<typename std::decay<Args>::type>::receive(args) ...);
241+
}
242+
};
243+
244+
template <typename T, typename Ret, typename ... Args, Ret (T::*fn)(Args ...)>
245+
struct em_wrap_fn<Ret (T::*)(Args ...), fn>
246+
{
247+
static typename em_wrap_type<typename std::decay<Ret>::type>::WireType wrap(T & t, typename em_wrap_type<typename std::decay<Args>::type>::WireType ... args)
248+
{
249+
return em_wrap_type<typename std::decay<Ret>::type>::transmit((t.*fn)(em_wrap_type<typename std::decay<Args>::type>::receive(args) ...));
250+
}
251+
};
252+
253+
template <typename T, typename Ret, typename ... Args, Ret (T::*fn)(Args ...) const>
254+
struct em_wrap_fn<Ret (T::*)(Args ...) const, fn>
255+
{
256+
static typename em_wrap_type<typename std::decay<Ret>::type>::WireType wrap(T const & t, typename em_wrap_type<typename std::decay<Args>::type>::WireType ... args)
257+
{
258+
return em_wrap_type<typename std::decay<Ret>::type>::transmit((t.*fn)(em_wrap_type<typename std::decay<Args>::type>::receive(args) ...));
259+
}
260+
};
261+
262+
template <typename T, typename ... Args, void (*fn)(T &, Args ...)>
263+
struct em_wrap_fn<void (*)(T &, Args ...), fn>
264+
{
265+
static void wrap(T & t, typename em_wrap_type<typename std::decay<Args>::type>::WireType ... args)
266+
{
267+
return fn(t, em_wrap_type<typename std::decay<Args>::type>::receive(args) ...);
268+
}
269+
};
270+
271+
template <typename T, typename ... Args, void (*fn)(T const &, Args ...)>
272+
struct em_wrap_fn<void (*)(T const &, Args ...), fn>
273+
{
274+
static void wrap(T const & t, typename em_wrap_type<typename std::decay<Args>::type>::WireType ... args)
275+
{
276+
return fn(t, em_wrap_type<typename std::decay<Args>::type>::receive(args) ...);
277+
}
278+
};
279+
280+
template <typename T, typename Ret, typename ... Args, Ret (*fn)(T &, Args ...)>
281+
struct em_wrap_fn<Ret (*)(T &, Args ...), fn>
282+
{
283+
static typename em_wrap_type<typename std::decay<Ret>::type>::WireType wrap(T & t, typename em_wrap_type<typename std::decay<Args>::type>::WireType ... args)
284+
{
285+
return em_wrap_type<typename std::decay<Ret>::type>::transmit(fn(t, em_wrap_type<typename std::decay<Args>::type>::receive(args) ...));
286+
}
287+
};
288+
289+
template <typename T, typename Ret, typename ... Args, Ret (*fn)(T const &, Args ...)>
290+
struct em_wrap_fn<Ret (*)(T const &, Args ...), fn>
291+
{
292+
static typename em_wrap_type<typename std::decay<Ret>::type>::WireType wrap(T const & t, typename em_wrap_type<typename std::decay<Args>::type>::WireType ... args)
293+
{
294+
return em_wrap_type<typename std::decay<Ret>::type>::transmit(fn(t, em_wrap_type<typename std::decay<Args>::type>::receive(args) ...));
295+
}
296+
};
297+
298+
/********** **********/
299+
300+
template <typename T, T>
301+
struct em_wrap_static_fn;
302+
303+
template <typename ... Args, void (*fn)(Args ...)>
304+
struct em_wrap_static_fn<void (*)(Args ...), fn>
305+
{
306+
static void wrap(typename em_wrap_type<typename std::decay<Args>::type>::WireType ... args)
307+
{
308+
return fn(em_wrap_type<typename std::decay<Args>::type>::receive(args) ...);
309+
}
310+
};
311+
312+
template <typename Ret, typename ... Args, Ret (*fn)(Args ...)>
313+
struct em_wrap_static_fn<Ret (*)(Args ...), fn>
314+
{
315+
static typename em_wrap_type<typename std::decay<Ret>::type>::WireType wrap(typename em_wrap_type<typename std::decay<Args>::type>::WireType ... args)
316+
{
317+
return em_wrap_type<typename std::decay<Ret>::type>::transmit(fn(em_wrap_type<typename std::decay<Args>::type>::receive(args) ...));
318+
}
319+
};
320+
321+
/********** **********/
322+
323+
template <typename T, T>
324+
struct em_wrap_property;
325+
326+
template <typename T, typename PropertyType, PropertyType T::*property>
327+
struct em_wrap_property<PropertyType T::*, property>
328+
{
329+
static typename em_wrap_type<typename std::decay<PropertyType>::type>::WireType get(T const & t)
330+
{
331+
return em_transmit(t.*property);
332+
}
333+
334+
static void set(T & t, typename em_wrap_type<typename std::decay<PropertyType>::type>::WireType wire)
335+
{
336+
t.*property = em_receive<PropertyType>(wire);
337+
}
338+
};
339+
340+
/********** **********/
341+
342+
#define WRAP(FN) WRAP_OVERLOAD((FN), decltype(FN))
343+
#define WRAP_OVERLOAD(FN, ...) &em_wrap_fn<__VA_ARGS__, (FN)>::wrap
344+
345+
#define WRAP_STATIC(FN) WRAP_STATIC_OVERLOAD((FN), decltype(FN))
346+
#define WRAP_STATIC_OVERLOAD(FN, ...) &em_wrap_static_fn<__VA_ARGS__, (FN)>::wrap
347+
348+
#define WRAP_FIELD(CLASS, FIELD) &em_wrap_property<decltype(&CLASS::FIELD), &CLASS::FIELD>::get, &em_wrap_property<decltype(&CLASS::FIELD), &CLASS::FIELD>::set

0 commit comments

Comments
 (0)