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
2 changes: 1 addition & 1 deletion src/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ var EXPORTED_FUNCTIONS = ['_main'];
var EXPORT_ALL = 0; // If true, we export all the symbols. Note that this does *not* affect LLVM, so it can
// still eliminate functions as dead. This just exports them on the Module object.
var EXPORT_BINDINGS = 0; // Export all bindings generator functions (prefixed with emscripten_bind_). This
// is necessary to use the WebIDL binder or bindings generator with asm.js
// is necessary to use the WebIDL binder with asm.js
var EXPORT_FUNCTION_TABLES = 0; // If true, export all the functions appearing in a function table, and the
// tables themselves.
var RETAIN_COMPILER_SETTINGS = 0; // Remembers the values of these settings, and makes them accessible
Expand Down
294 changes: 0 additions & 294 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -6470,300 +6470,6 @@ def test_embind_f_no_rtti(self):
'''
self.do_run(src, '418')

@sync
@no_wasm_backend()
def test_scriptaclass(self):
Settings.EXPORT_BINDINGS = 1

header_filename = os.path.join(self.get_dir(), 'header.h')
header = '''
struct ScriptMe {
int value;
ScriptMe(int val);
int getVal(); // XXX Sadly, inlining these will result in LLVM not
// producing any code for them (when just building
// as a library)
void mulVal(int mul);
};
'''
h = open(header_filename, 'w')
h.write(header)
h.close()

src = '''
#include "header.h"

ScriptMe::ScriptMe(int val) : value(val) { }
int ScriptMe::getVal() { return value; }
void ScriptMe::mulVal(int mul) { value *= mul; }
'''

# Way 1: use demangler and namespacer

script_src = '''
var sme = Module._.ScriptMe.__new__(83); // malloc(sizeof(ScriptMe)), ScriptMe::ScriptMe(sme, 83) / new ScriptMe(83) (at addr sme)
Module._.ScriptMe.mulVal(sme, 2); // ScriptMe::mulVal(sme, 2) sme.mulVal(2)
Module.print('*' + Module._.ScriptMe.getVal(sme) + '*');
_free(sme);
Module.print('*ok*');
'''
post = '''
def process(filename):
Popen([PYTHON, DEMANGLER, filename], stdout=open(filename + '.tmp', 'w')).communicate()
Popen([PYTHON, NAMESPACER, filename, filename + '.tmp'], stdout=open(filename + '.tmp2', 'w')).communicate()
src = open(filename, 'r').read().replace(
'// {{MODULE_ADDITIONS}',
'Module["_"] = ' + open(filename + '.tmp2', 'r').read().replace('var ModuleNames = ', '').rstrip() + ';\n\n' + script_src + '\n\n' +
'// {{MODULE_ADDITIONS}'
)
open(filename, 'w').write(src)
'''
# XXX disable due to possible v8 bug -- self.do_run(src, '*166*\n*ok*', post_build=post)

if '-O2' in self.emcc_args and 'ASM_JS=0' not in self.emcc_args: # without asm, closure minifies Math.imul badly
self.emcc_args += ['--closure', '1'] # Use closure here, to test we export things right

# Way 2: use CppHeaderParser

header = '''
#include <stdio.h>

class Parent {
protected:
int value;
public:
Parent(int val);
Parent(Parent *p, Parent *q); // overload constructor
int getVal() { return value; }; // inline should work just fine here, unlike Way 1 before
void mulVal(int mul);
};

class Child1 : public Parent {
public:
Child1() : Parent(7) { printf("Child1:%d\\n", value); };
Child1(int val) : Parent(val*2) { value -= 1; printf("Child1:%d\\n", value); };
int getValSqr() { return value*value; }
int getValSqr(int more) { return value*value*more; }
int getValTimes(int times=1) { return value*times; }
};

class Child2 : public Parent {
public:
Child2() : Parent(9) { printf("Child2:%d\\n", value); };
int getValCube() { return value*value*value; }
static void printStatic() { printf("*static*\\n"); }

virtual void virtualFunc() { printf("*virtualf*\\n"); }
virtual void virtualFunc2() { printf("*virtualf2*\\n"); }
static void runVirtualFunc(Child2 *self) { self->virtualFunc(); };
private:
void doSomethingSecret() { printf("security breached!\\n"); }; // we should not be able to do this
};
'''
open(header_filename, 'w').write(header)

basename = os.path.join(self.get_dir(), 'bindingtest')
output = Popen([PYTHON, BINDINGS_GENERATOR, basename, header_filename], stdout=PIPE, stderr=self.stderr_redirect).communicate()[0]
#print output
assert 'Traceback' not in output, 'Failure in binding generation: ' + output

src = '''
#include "header.h"

Parent::Parent(int val) : value(val) { printf("Parent:%d\\n", val); }
Parent::Parent(Parent *p, Parent *q) : value(p->value + q->value) { printf("Parent:%d\\n", value); }
void Parent::mulVal(int mul) { value *= mul; }

#include "bindingtest.cpp"
'''

post2 = '''
def process(filename):
src = open(filename, 'a')
src.write(open('bindingtest.js').read() + '\\n\\n')
src.close()
'''

def post3(filename):
script_src_2 = '''
var sme = new Module.Parent(42);
sme.mulVal(2);
Module.print('*')
Module.print(sme.getVal());

Module.print('c1');

var c1 = new Module.Child1();
Module.print(c1.getVal());
c1.mulVal(2);
Module.print(c1.getVal());
Module.print(c1.getValSqr());
Module.print(c1.getValSqr(3));
Module.print(c1.getValTimes()); // default argument should be 1
Module.print(c1.getValTimes(2));

Module.print('c1 v2');

c1 = new Module.Child1(8); // now with a parameter, we should handle the overloading automatically and properly and use constructor #2
Module.print(c1.getVal());
c1.mulVal(2);
Module.print(c1.getVal());
Module.print(c1.getValSqr());
Module.print(c1.getValSqr(3));

Module.print('c2')

var c2 = new Module.Child2();
Module.print(c2.getVal());
c2.mulVal(2);
Module.print(c2.getVal());
Module.print(c2.getValCube());
var succeeded;
try {
succeeded = 0;
Module.print(c2.doSomethingSecret()); // should fail since private
succeeded = 1;
} catch(e) {}
Module.print(succeeded);
try {
succeeded = 0;
Module.print(c2.getValSqr()); // function from the other class
succeeded = 1;
} catch(e) {}
Module.print(succeeded);
try {
succeeded = 0;
c2.getValCube(); // sanity
succeeded = 1;
} catch(e) {}
Module.print(succeeded);

Module.Child2.prototype.printStatic(); // static calls go through the prototype

// virtual function
c2.virtualFunc();
Module.Child2.prototype.runVirtualFunc(c2);
c2.virtualFunc2();

// extend the class from JS
var c3 = new Module.Child2;
Module.customizeVTable(c3, [{
original: Module.Child2.prototype.virtualFunc,
replacement: function() {
Module.print('*js virtualf replacement*');
}
}, {
original: Module.Child2.prototype.virtualFunc2,
replacement: function() {
Module.print('*js virtualf2 replacement*');
}
}]);
c3.virtualFunc();
Module.Child2.prototype.runVirtualFunc(c3);
c3.virtualFunc2();

c2.virtualFunc(); // original should remain the same
Module.Child2.prototype.runVirtualFunc(c2);
c2.virtualFunc2();
Module.print('*ok*');
'''
code = open(filename).read()
src = open(filename, 'w')
src.write('var Module = {};\n') # name Module
src.write(code)
src.write(script_src_2 + '\n')
src.close()

Settings.RESERVED_FUNCTION_POINTERS = 20

self.do_run(src, '''*
84
c1
Parent:7
Child1:7
7
14
196
588
14
28
c1 v2
Parent:16
Child1:15
15
30
900
2700
c2
Parent:9
Child2:9
9
18
5832
0
0
1
*static*
*virtualf*
*virtualf*
*virtualf2*''' + ('''
Parent:9
Child2:9
*js virtualf replacement*
*js virtualf replacement*
*js virtualf2 replacement*
*virtualf*
*virtualf*
*virtualf2*''') + '''
*ok*
''', post_build=(post2, post3))

@sync
@no_wasm_backend()
def test_scriptaclass_2(self):
Settings.EXPORT_BINDINGS = 1

header_filename = os.path.join(self.get_dir(), 'header.h')
header = '''
#include <stdio.h>
#include <string.h>

class StringUser {
char *s;
int i;
public:
StringUser(char *string, int integer) : s(strdup(string)), i(integer) {}
void Print(int anotherInteger, char *anotherString) {
printf("|%s|%d|%s|%d|\\n", s, i, anotherString, anotherInteger);
}
void CallOther(StringUser *fr) { fr->Print(i, s); }
};
'''
open(header_filename, 'w').write(header)

basename = os.path.join(self.get_dir(), 'bindingtest')
output = Popen([PYTHON, BINDINGS_GENERATOR, basename, header_filename], stdout=PIPE, stderr=self.stderr_redirect).communicate()[0]
#print output
assert 'Traceback' not in output, 'Failure in binding generation: ' + output

src = '''
#include "header.h"

#include "bindingtest.cpp"
'''

post = '''
def process(filename):
src = open(filename, 'a')
src.write(open('bindingtest.js').read() + '\\n\\n')
src.write(\'\'\'
var user = new Module.StringUser("hello", 43);
user.Print(41, "world");
\'\'\')
src.close()
'''
self.do_run(src, '|hello|43|world|41|', post_build=post)

@sync
@no_wasm_backend()
def test_webidl(self):
Expand Down
Loading