Skip to content

Commit 5821ef0

Browse files
committed
WebAssembly: node polyfill code and build script
1 parent 5ebc5d5 commit 5821ef0

File tree

11 files changed

+648
-3
lines changed

11 files changed

+648
-3
lines changed

Makefile

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ else
2727
endif
2828
CAT ?= $(if $(filter $(OS),Windows_NT),type,cat)
2929

30+
ifdef WASM
31+
CFLAGS += -D_WASM
32+
CXXFLAGS += -D_WASM
33+
endif
34+
35+
ifdef WASM
36+
UNAME := WebAssembly
37+
else
3038
ifneq (,$(findstring /cygdrive/,$(PATH)))
3139
UNAME := Cygwin
3240
else
@@ -44,6 +52,7 @@ endif
4452
endif
4553
endif
4654
endif
55+
endif
4756

4857
ifndef LIBSASS_VERSION
4958
ifneq ($(wildcard ./.git/ ),)
@@ -161,18 +170,28 @@ ifeq (Windows,$(UNAME))
161170
LIB_SHARED = $(SASS_LIBSASS_PATH)/lib/libsass.dll
162171
endif
163172
else
173+
ifdef WASM
174+
SASSC_BIN = $(SASS_SASSC_PATH)/bin/sassc.wasm
175+
SHAREDLIB = lib/libsass.wasm
176+
LIB_SHARED = $(SASS_LIBSASS_PATH)/lib/libsass.wasm
177+
else
164178
ifneq (Cygwin,$(UNAME))
165179
CFLAGS += -fPIC
166180
CXXFLAGS += -fPIC
167181
LDFLAGS += -fPIC
168182
endif
169183
endif
184+
endif
170185

171186
include Makefile.conf
172187
OBJECTS = $(addprefix src/,$(SOURCES:.cpp=.o))
173188
COBJECTS = $(addprefix src/,$(CSOURCES:.c=.o))
174189
RCOBJECTS = $(RESOURCES:.rc=.o)
175190

191+
ifdef WASM
192+
WASMOBJECTS = wasm/libcxxabi_stubs.o
193+
endif
194+
176195
DEBUG_LVL ?= NONE
177196

178197
CLEANUPS ?=
@@ -198,15 +217,18 @@ debug-shared: shared
198217
lib:
199218
$(MKDIR) lib
200219

201-
lib/libsass.a: $(COBJECTS) $(OBJECTS) | lib
202-
$(AR) rcvs $@ $(COBJECTS) $(OBJECTS)
220+
lib/libsass.a: $(COBJECTS) $(OBJECTS) $(WASMOBJECTS) | lib
221+
$(AR) rcvs $@ $(COBJECTS) $(OBJECTS) $(WASMOBJECTS)
203222

204223
lib/libsass.so: $(COBJECTS) $(OBJECTS) | lib
205224
$(CXX) -shared $(LDFLAGS) -o $@ $(COBJECTS) $(OBJECTS) $(LDLIBS)
206225

207226
lib/libsass.dll: $(COBJECTS) $(OBJECTS) $(RCOBJECTS) | lib
208227
$(CXX) -shared $(LDFLAGS) -o $@ $(COBJECTS) $(OBJECTS) $(RCOBJECTS) $(LDLIBS) -s -Wl,--subsystem,windows,--out-implib,lib/libsass.a
209228

229+
lib/libsass.wasm: $(COBJECTS) $(OBJECTS) $(WASMOBJECTS) | lib
230+
$(CXX) $(LDFLAGS) -o $@ $(COBJECTS) $(OBJECTS) $(WASMOBJECTS) $(LDLIBS)
231+
210232
%.o: %.c
211233
$(CC) $(CFLAGS) -c -o $@ $<
212234

@@ -269,7 +291,9 @@ $(SASSC_BIN): $(BUILD)
269291
$(MAKE) -C $(SASS_SASSC_PATH) build-$(BUILD)-dev
270292

271293
sassc: $(SASSC_BIN)
294+
ifndef WASM
272295
$(SASSC_BIN) -v
296+
endif
273297

274298
version: $(SASSC_BIN)
275299
$(SASSC_BIN) -v
@@ -286,7 +310,7 @@ test_probe: $(SASSC_BIN)
286310
$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -c $(SASSC_BIN) --impl libsass --probe-todo $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)
287311

288312
clean-objects: | lib
289-
-$(RM) lib/*.a lib/*.so lib/*.dll lib/*.la
313+
-$(RM) lib/*.a lib/*.so lib/*.dll lib/*.la lib/*.wasm
290314
-$(RMDIR) lib
291315
clean: clean-objects
292316
$(RM) $(CLEANUPS)

src/file.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ namespace Sass {
5858
std::string get_cwd()
5959
{
6060
const size_t wd_len = 4096;
61+
#ifdef _WASM
62+
std::string cwd = "/";
63+
#else
6164
#ifndef _WIN32
6265
char wd[wd_len];
6366
char* pwd = getcwd(wd, wd_len);
@@ -73,6 +76,7 @@ namespace Sass {
7376
//convert backslashes to forward slashes
7477
replace(cwd.begin(), cwd.end(), '\\', '/');
7578
#endif
79+
#endif
7680
if (cwd[cwd.length() - 1] != '/') cwd += '/';
7781
return cwd;
7882
}

src/plugins.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313
#include <sys/types.h>
1414
#include <dirent.h>
1515
#include <errno.h>
16+
#ifndef _WASM
1617
#include <dlfcn.h>
1718
#endif
19+
#endif
1820

1921
namespace Sass {
2022

@@ -62,6 +64,7 @@ namespace Sass {
6264
typedef Sass_Function_List (*__plugin_load_fns__)(void);
6365
typedef Sass_Importer_List (*__plugin_load_imps__)(void);
6466

67+
#ifndef _WASM
6568
if (LOAD_LIB(plugin, path))
6669
{
6770
// try to load initial function to query libsass version suppor
@@ -107,6 +110,9 @@ namespace Sass {
107110
std::cerr << "failed loading plugin <" << path << ">" << std::endl;
108111
if (const char* dlopen_error = dlerror()) std::cerr << dlopen_error << std::endl;
109112
}
113+
#else
114+
std::cerr << "loading plugin unsupported <" << path << ">" << std::endl;
115+
#endif
110116

111117
return false;
112118

wasm/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
*.sass
2+
*.css
3+
*.css.map

wasm/Makefile

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
WASI_SDK ?= ~/bin/wasi-sdk
2+
MAKE_OPTS = \
3+
CC=$(WASI_SDK)/bin/clang \
4+
CXX=$(WASI_SDK)/bin/clang++ \
5+
AR=$(WASI_SDK)/bin/llvm-ar \
6+
WASM=1
7+
WABT ?= ~/Work/wabt
8+
9+
build:
10+
$(MAKE) -C .. $(MAKE_OPTS) sassc
11+
12+
clean:
13+
$(MAKE) -C .. $(MAKE_OPTS) clean-all
14+
15+
wasi_polyfill.wasm: wasi_polyfill.wat
16+
$(WABT)/bin/wat2wasm wasi_polyfill.wat -o wasi_polyfill.wasm
17+
18+
.PHONY: build clean

wasm/README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Building
2+
3+
To build `../sassc/bin/sassc.wasm`:
4+
5+
* Clone https://github.com/yurydelendik/sassc into parent (libsass) folder
6+
* Run `make`
7+
8+
To rebuild `wasi_polyfill.wasm`: `make wasi_polyfill.wasm`
9+
10+
# Running
11+
12+
Examples:
13+
14+
```
15+
node run.js -v
16+
node run.js $PWD/test.sass
17+
node run.js $PWD/test.sass $PWD/test.css
18+
```
19+
20+
Note: Use full path for the file names and only in the current dir (hence `$PWD/` prefix).
21+
22+

wasm/libcxxabi_stubs.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#include <stdlib.h>
2+
3+
// -fno-exceptions is not an option with libsass yet,
4+
// stubbing libc++abi functions
5+
6+
void __cxa_throw(void *thrown_exception, void *tinfo,
7+
void (*dest)(void *))
8+
{
9+
abort();
10+
}
11+
12+
void *__cxa_allocate_exception(size_t thrown_size)
13+
{
14+
abort();
15+
}
16+
17+
void __cxa_rethrow()
18+
{
19+
abort();
20+
}
21+
22+
void* __cxa_begin_catch(void* exceptionObject)
23+
{
24+
abort();
25+
}

wasm/run.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
const wp = require('./wasi_polyfill.js');
2+
const fs = require('fs');
3+
4+
async function init() {
5+
const host = new wp.createWasiHost();
6+
const { instance: wrapper } = await WebAssembly.instantiate(
7+
fs.readFileSync("wasi_polyfill.wasm"),
8+
{"wasi_polyfill": host}
9+
);
10+
const { instance: sassc } = await WebAssembly.instantiate(
11+
fs.readFileSync("../sassc/bin/sassc.wasm"),
12+
{"wasi_unstable": wrapper.exports}
13+
);
14+
host.args = ["../sassc/bin/sassc.wasm", ...process.argv.slice(2)];
15+
host.memory = sassc.exports.memory;
16+
return sassc.exports;
17+
}
18+
19+
init().then(sassc => {
20+
try {
21+
sassc._start();
22+
} catch (e) {
23+
if (e.message != "proc_exit") throw e;
24+
}
25+
}, console.error);

0 commit comments

Comments
 (0)