Another day, another interface

Change the interface again, hopefully this time a bit more normal.
Now we wrap the emscripten module completely and just expose the
high level objects.

The olm library export is now imported as normal (ie. returns
a module rather than a function returning a module) but has an
`init` method which *must* be called. This returns a promise
which resolves when the module is ready. It also rejects if the
module failed to set up, unlike before (and unlike the
promise-not-a-promise that emscripten returns).

Generally catch failures to init the module.
This commit is contained in:
David Baker 2018-09-25 17:13:29 +01:00
parent f29d8cdd7b
commit 263b94428a
9 changed files with 83 additions and 41 deletions

View file

@ -41,11 +41,22 @@ FUZZER_BINARIES := $(addprefix $(BUILD_DIR)/,$(basename $(FUZZER_SOURCES)))
FUZZER_DEBUG_BINARIES := $(patsubst $(BUILD_DIR)/fuzzers/fuzz_%,$(BUILD_DIR)/fuzzers/debug_%,$(FUZZER_BINARIES)) FUZZER_DEBUG_BINARIES := $(patsubst $(BUILD_DIR)/fuzzers/fuzz_%,$(BUILD_DIR)/fuzzers/debug_%,$(FUZZER_BINARIES))
TEST_BINARIES := $(patsubst tests/%,$(BUILD_DIR)/tests/%,$(basename $(TEST_SOURCES))) TEST_BINARIES := $(patsubst tests/%,$(BUILD_DIR)/tests/%,$(basename $(TEST_SOURCES)))
JS_OBJECTS := $(addprefix $(BUILD_DIR)/javascript/,$(OBJECTS)) JS_OBJECTS := $(addprefix $(BUILD_DIR)/javascript/,$(OBJECTS))
# pre & post are the js-pre/js-post options to emcc.
# They are injected inside the modularised code and
# processed by the optimiser.
JS_PRE := $(wildcard javascript/*pre.js) JS_PRE := $(wildcard javascript/*pre.js)
JS_POST := javascript/olm_outbound_group_session.js \ JS_POST := javascript/olm_outbound_group_session.js \
javascript/olm_inbound_group_session.js \ javascript/olm_inbound_group_session.js \
javascript/olm_pk.js \ javascript/olm_pk.js \
javascript/olm_post.js javascript/olm_post.js
# The prefix & suffix are just added onto the start & end
# of what comes out emcc, so are outside of the modularised
# code and not seen by the opimiser.
JS_PREFIX := javascript/olm_prefix.js
JS_SUFFIX := javascript/olm_suffix.js
DOCS := tracing/README.html \ DOCS := tracing/README.html \
docs/megolm.html \ docs/megolm.html \
docs/olm.html \ docs/olm.html \
@ -67,6 +78,15 @@ EMCCFLAGS = --closure 1 --memory-init-file 0 -s NO_FILESYSTEM=1 -s INVOKE_RUN=0
# longer needed. # longer needed.
EMCCFLAGS += -s NO_BROWSER=1 EMCCFLAGS += -s NO_BROWSER=1
# Olm generally doesn't need a lot of memory to encrypt / decrypt its usual
# payloads (ie. Matrix messages), but we do need about 128K of heap to encrypt
# a 64K event (enough to store the ciphertext and the plaintext, bearing in
# mind that the plaintext can only be 48K because base64). We also have about
# 36K of statics. So let's have 256K of memory.
# (This can't be changed by the app with wasm since it's baked into the wasm).
EMCCFLAGS += -s TOTAL_STACK=65536 -s TOTAL_MEMORY=262144
EMCC.c = $(EMCC) $(CFLAGS) $(CPPFLAGS) -c EMCC.c = $(EMCC) $(CFLAGS) $(CPPFLAGS) -c
EMCC.cc = $(EMCC) $(CXXFLAGS) $(CPPFLAGS) -c EMCC.cc = $(EMCC) $(CXXFLAGS) $(CPPFLAGS) -c
EMCC_LINK = $(EMCC) $(LDFLAGS) $(EMCCFLAGS) EMCC_LINK = $(EMCC) $(LDFLAGS) $(EMCCFLAGS)
@ -147,13 +167,19 @@ $(STATIC_RELEASE_TARGET): $(RELEASE_OBJECTS)
js: $(JS_TARGET) js: $(JS_TARGET)
.PHONY: js .PHONY: js
$(JS_TARGET): $(JS_OBJECTS) $(JS_PRE) $(JS_POST) $(JS_EXPORTED_FUNCTIONS) # Note that the output file we give to emcc determines the name of the
# wasm file baked into the js, hence messing around outputting to olm.js
# and then renaming it.
$(JS_TARGET): $(JS_OBJECTS) $(JS_PRE) $(JS_POST) $(JS_EXPORTED_FUNCTIONS) $(JS_PREFIX) $(JS_SUFFIX)
EMCC_CLOSURE_ARGS="--externs $(JS_EXTERNS)" $(EMCC_LINK) \ EMCC_CLOSURE_ARGS="--externs $(JS_EXTERNS)" $(EMCC_LINK) \
$(foreach f,$(JS_PRE),--pre-js $(f)) \ $(foreach f,$(JS_PRE),--pre-js $(f)) \
$(foreach f,$(JS_POST),--post-js $(f)) \ $(foreach f,$(JS_POST),--post-js $(f)) \
-s "EXPORTED_FUNCTIONS=@$(JS_EXPORTED_FUNCTIONS)" \ -s "EXPORTED_FUNCTIONS=@$(JS_EXPORTED_FUNCTIONS)" \
-s "EXTRA_EXPORTED_RUNTIME_METHODS=$(JS_EXTRA_EXPORTED_RUNTIME_METHODS)" \ -s "EXTRA_EXPORTED_RUNTIME_METHODS=$(JS_EXTRA_EXPORTED_RUNTIME_METHODS)" \
$(JS_OBJECTS) -o $@ $(JS_OBJECTS) -o $@
mv $@ javascript/olmtmp.js
cat $(JS_PREFIX) javascript/olmtmp.js $(JS_SUFFIX) > $@
rm javascript/olmtmp.js
build_tests: $(TEST_BINARIES) build_tests: $(TEST_BINARIES)

View file

@ -1 +1,4 @@
var OLM_OPTIONS; var OLM_OPTIONS;
var olm_exports;
var onInitSuccess;
var onInitFail;

View file

@ -464,27 +464,11 @@ olm_exports["get_library_version"] = restore_stack(function() {
]; ];
}); });
// export the olm functions into the environment. Module['onRuntimeInitialized'] = function() {
//
// make sure that we do this *after* populating olm_exports, so that we don't
// get a half-built window.Olm if there is an exception.
if (typeof module !== 'undefined' && module.exports) {
// node / browserify
for (var olm_export in olm_exports) {
if (olm_exports.hasOwnProperty(olm_export)) {
Module[olm_export] = olm_exports[olm_export];
}
}
}
if (typeof(window) !== 'undefined') {
// We've been imported directly into a browser. Define the global 'Olm' object.
// (we do this even if module.exports was defined, because it's useful to have
// Olm in the global scope for browserified and webpacked apps.)
window["Olm"] = olm_exports;
}
Module.then(function() {
OLM_ERROR = Module['_olm_error'](); OLM_ERROR = Module['_olm_error']();
}); if (onInitSuccess) onInitSuccess();
};
Module['onAbort'] = function(err) {
if (onInitFail) onInitFail(err);
};

View file

@ -1,4 +1,3 @@
var olm_exports = {};
var get_random_values; var get_random_values;
if (typeof(window) !== 'undefined') { if (typeof(window) !== 'undefined') {

3
javascript/olm_prefix.js Normal file
View file

@ -0,0 +1,3 @@
var olm_exports = {};
var onInitSuccess;
var onInitFail;

23
javascript/olm_suffix.js Normal file
View file

@ -0,0 +1,23 @@
olm_exports['init'] = function() {
return new Promise(function(resolve, reject) {
onInitSuccess = function() {
resolve();
};
onInitFail = function(err) {
reject(err);
};
Module();
});
};
if (typeof(window) !== 'undefined') {
// We've been imported directly into a browser. Define the global 'Olm' object.
// (we do this even if module.exports was defined, because it's useful to have
// Olm in the global scope for browserified and webpacked apps.)
window["Olm"] = olm_exports;
}
// Emscripten sets the module exports to be its module
// with wrapped c functions. Clobber it with our higher
// level wrapper class.
module.exports = olm_exports;

View file

@ -1,5 +1,6 @@
/* /*
Copyright 2016 OpenMarket Ltd Copyright 2016 OpenMarket Ltd
Copyright 2018 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -16,17 +17,18 @@ limitations under the License.
"use strict"; "use strict";
var Olm = require('../olm')(); var Olm = require('../olm');
describe("megolm", function() { describe("megolm", function() {
var aliceSession, bobSession; var aliceSession, bobSession;
beforeEach(function(done) { beforeEach(function(done) {
Olm.then(function() { Olm.init().then(function() {
done();
});
aliceSession = new Olm.OutboundGroupSession(); aliceSession = new Olm.OutboundGroupSession();
bobSession = new Olm.InboundGroupSession(); bobSession = new Olm.InboundGroupSession();
done();
});
}); });
afterEach(function() { afterEach(function() {

View file

@ -1,5 +1,6 @@
/* /*
Copyright 2016 OpenMarket Ltd Copyright 2016 OpenMarket Ltd
Copyright 2018 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -16,7 +17,7 @@ limitations under the License.
"use strict"; "use strict";
var Olm = require('../olm')(); var Olm = require('../olm');
if (!Object.keys) { if (!Object.keys) {
Object.keys = function(o) { Object.keys = function(o) {
@ -33,14 +34,15 @@ describe("olm", function() {
beforeEach(function(done) { beforeEach(function(done) {
// This should really be in a beforeAll, but jasmine-node // This should really be in a beforeAll, but jasmine-node
// doesn't support that // doesn't support that
Olm.then(function() { debugger;
done(); Olm.init().then(function() {
});
aliceAccount = new Olm.Account(); aliceAccount = new Olm.Account();
bobAccount = new Olm.Account(); bobAccount = new Olm.Account();
aliceSession = new Olm.Session(); aliceSession = new Olm.Session();
bobSession = new Olm.Session(); bobSession = new Olm.Session();
done();
});
}); });
afterEach(function() { afterEach(function() {

View file

@ -16,7 +16,7 @@ limitations under the License.
"use strict"; "use strict";
var Olm = require('../olm')(); var Olm = require('../olm');
if (!Object.keys) { if (!Object.keys) {
Object.keys = function(o) { Object.keys = function(o) {
@ -30,12 +30,12 @@ describe("pk", function() {
var encryption, decryption; var encryption, decryption;
beforeEach(function(done) { beforeEach(function(done) {
Olm.then(function() { Olm.init().then(function() {
done();
});
encryption = new Olm.PkEncryption(); encryption = new Olm.PkEncryption();
decryption = new Olm.PkDecryption(); decryption = new Olm.PkDecryption();
done();
});
}); });
afterEach(function () { afterEach(function () {