| |
| // Part 1 |
| |
| var sme = new TheModule.Parent(42); |
| sme.mulVal(2); |
| console.log('*') |
| console.log(sme.getVal()); |
| sme.parentFunc(90); |
| console.log(typeof sme.getAsConst()); |
| console.log(typeof sme.voidStar(sme)); |
| console.log(sme.get_immutableAttr()); |
| console.log(sme.immutableAttr); |
| |
| try { |
| sme.immutableAttr = 1; |
| } catch(e) {} |
| console.log(sme.immutableAttr); // Should be unchanged |
| console.log(sme.attr); |
| console.log(sme.get_attr()); |
| sme.attr = 9; |
| console.log(sme.attr); |
| sme.set_attr(10); |
| console.log(sme.attr); |
| console.log(sme.get_attr()); |
| |
| console.log(typeof sme.getBoolean()); |
| console.log(sme.getBoolean()); |
| |
| console.log('c1'); |
| |
| var c1 = new TheModule.Child1(); |
| console.log(c1.getVal()); |
| c1.mulVal(2); |
| console.log(c1.getVal()); |
| console.log(c1.getValSqr()); |
| console.log(c1.getValSqr(3)); |
| console.log(c1.getValTimes()); // default argument should be 1 |
| console.log(c1.getValTimes(2)); |
| console.log(sme.getBoolean()); |
| c1.parentFunc(90); |
| |
| console.log('c1 v2'); |
| |
| c1 = new TheModule.Child1(8); // now with a parameter, we should handle the overloading automatically and properly and use constructor #2 |
| console.log(c1.getVal()); |
| c1.mulVal(2); |
| console.log(c1.getVal()); |
| console.log(c1.getValSqr()); |
| console.log(c1.getValSqr(3)); |
| console.log(sme.getBoolean()); |
| |
| console.log('c2') |
| |
| var c2 = new TheModule.Child2(); |
| console.log(c2.getVal()); |
| c2.mulVal(2); |
| console.log(c2.getVal()); |
| console.log(c2.getValCube()); |
| var succeeded; |
| try { |
| succeeded = 0; |
| console.log(c2.doSomethingSecret()); // should fail since private |
| succeeded = 1; |
| } catch(e) {} |
| console.log(succeeded); |
| try { |
| succeeded = 0; |
| console.log(c2.getValSqr()); // function from the other class |
| succeeded = 1; |
| } catch(e) {} |
| console.log(succeeded); |
| try { |
| succeeded = 0; |
| c2.getValCube(); // sanity |
| succeeded = 1; |
| } catch(e) {} |
| console.log(succeeded); |
| |
| TheModule.Child2.prototype.printStatic(); // static calls go through the prototype |
| |
| // virtual function |
| c2.virtualFunc(); |
| TheModule.Child2.prototype.runVirtualFunc(c2); |
| c2.virtualFunc2(); |
| |
| // extend a class from JS |
| var c3 = new TheModule.Child2JS; |
| |
| c3.virtualFunc = function() { |
| console.log('*js virtualf replacement*'); |
| }; |
| c3.virtualFunc2 = function() { |
| console.log('*js virtualf2 replacement*'); |
| }; |
| c3.virtualFunc3 = function(x) { |
| console.log('*js virtualf3 replacement ' + x + '*'); |
| }; |
| |
| c3.virtualFunc(); |
| TheModule.Child2.prototype.runVirtualFunc(c3); |
| c3.virtualFunc2(); |
| c3.virtualFunc3(123); // this one is not replaced! |
| try { |
| c3.virtualFunc4(123); |
| } catch(e) { |
| console.log('caught: ' + e); |
| } |
| |
| // Test virtual method dispatch from c++ |
| TheModule.Child2.prototype.runVirtualFunc3(c3, 43); |
| |
| c2.virtualFunc(); // original should remain the same |
| TheModule.Child2.prototype.runVirtualFunc(c2); |
| c2.virtualFunc2(); |
| console.log('*ok*'); |
| |
| // Part 2 |
| |
| var suser = new TheModule.StringUser("hello", 43); |
| suser.Print(41, "world"); |
| suser.PrintFloat(12.3456); |
| console.log(suser.returnAString()); |
| |
| var bv = new TheModule.RefUser(10); |
| var bv2 = new TheModule.RefUser(11); |
| console.log(bv2.getValue(bv)); |
| |
| console.log(typeof bv2.getMe()); |
| console.log(bv2.getMe().getValue(bv)); |
| console.log(bv2.getMe().getValue(bv2)); |
| |
| console.log(typeof bv2.getCopy()); |
| console.log(bv2.getCopy().getValue(bv)); |
| console.log(bv2.getCopy().getValue(bv2)); |
| |
| bv2.getAnother().PrintFloat(21.12); |
| |
| console.log(new TheModule.Inner().get()); |
| console.log('getAsArray: ' + new TheModule.Inner().getAsArray(12)); |
| new TheModule.Inner().mul(2); |
| new TheModule.Inner().incInPlace(new TheModule.Inner()); |
| |
| console.log(TheModule.enum_value1); |
| console.log(TheModule.enum_value2); |
| |
| // Enums from classes are accessed via the class. |
| enumClassInstance = new TheModule.EnumClass(); |
| console.log([enumClassInstance.GetEnum(), TheModule.EnumClass.e_val].join(',')); |
| |
| // Enums from namespaces are accessed via the top-level module, as with classes defined |
| // in namespaces, see `Inner` above. |
| console.log(TheModule.e_namespace_val); |
| |
| typeTester = new TheModule.TypeTestClass(); |
| |
| console.log('return char ' + typeTester.ReturnCharMethod()); |
| typeTester.AcceptCharMethod((2<<6)-1); |
| // Prints -1 because the c++ code accepts unsigned char. |
| typeTester.AcceptCharMethod((2<<7)-1); |
| |
| // Prints -1 because all integers are signed in javascript. |
| console.log('return unsigned char ' + typeTester.ReturnUnsignedCharMethod()); |
| typeTester.AcceptUnsignedCharMethod((2<<7)-1); |
| |
| // Prints -1 because all integers are signed in javascript. |
| console.log('return unsigned short ' + typeTester.ReturnUnsignedShortMethod()); |
| typeTester.AcceptUnsignedShortMethod((2<<15)-1); |
| |
| // Prints -1 because all integers are signed in javascript. |
| console.log('return unsigned long ' + typeTester.ReturnUnsignedLongMethod()); |
| typeTester.AcceptUnsignedLongMethod((2<<31)-1); |
| var voidPointerUser = new TheModule.VoidPointerUser(); |
| |
| voidPointerUser.SetVoidPointer(3); |
| console.log('void * ' + voidPointerUser.GetVoidPointer()); |
| |
| // Array tests |
| |
| var arrayClass = new TheModule.ArrayClass(); |
| console.log('int_array[0] == ' + arrayClass.get_int_array(0)); |
| console.log('int_array[7] == ' + arrayClass.get_int_array(7)); |
| arrayClass.set_int_array(0, 42); |
| arrayClass.set_int_array(7, 43); |
| console.log('int_array[0] == ' + arrayClass.get_int_array(0)); |
| console.log('int_array[7] == ' + arrayClass.get_int_array(7)); |
| |
| try { |
| arrayClass.set_int_array(-1, struct); |
| } catch (e) { |
| console.log('idx -1: ' + e); |
| } |
| |
| try { |
| arrayClass.set_int_array(8, struct); |
| } catch (e) { |
| console.log('idx 8: ' + e); |
| } |
| |
| console.log('struct_array[0].attr1 == ' + arrayClass.get_struct_array(0).get_attr1()); |
| console.log('struct_array[0].attr2 == ' + arrayClass.get_struct_array(0).get_attr2()); |
| console.log('struct_array[7].attr1 == ' + arrayClass.get_struct_array(7).get_attr1()); |
| console.log('struct_array[7].attr2 == ' + arrayClass.get_struct_array(7).get_attr2()); |
| |
| // Verify that bounds checking is *not* enabled when not asked for. |
| // This actually causes an illegal memory access, but as it's only a read, and the return |
| // value is not used, it shouldn't cause any problems in practice. |
| arrayClass.get_struct_array(8); |
| |
| var struct = new TheModule.StructInArray(13, 17); |
| arrayClass.set_struct_array(0, struct); |
| struct = new TheModule.StructInArray(14, 18); |
| arrayClass.set_struct_array(7, struct); |
| |
| console.log('struct_array[0].attr1 == ' + arrayClass.get_struct_array(0).get_attr1()); |
| console.log('struct_array[0].attr2 == ' + arrayClass.get_struct_array(0).get_attr2()); |
| console.log('struct_array[7].attr1 == ' + arrayClass.get_struct_array(7).get_attr1()); |
| console.log('struct_array[7].attr2 == ' + arrayClass.get_struct_array(7).get_attr2()); |
| |
| struct = new TheModule.StructInArray(100, 101); |
| arrayClass.set_struct_ptr_array(0, struct); |
| console.log('struct_ptr_array[0]->attr1 == ' + arrayClass.get_struct_ptr_array(0).get_attr1()); |
| console.log('struct_ptr_array[0]->attr2 == ' + arrayClass.get_struct_ptr_array(0).get_attr2()); |
| |
| // receiving arrays |
| |
| var receiver = new TheModule.ReceiveArrays(); |
| receiver.giveMeArrays([0.5, 0.25, 0.01, -20.42], [1, 4, 9, 10], 4); |
| |
| // Test IDL_CHECKS=ALL |
| |
| try { |
| p = new TheModule.Parent(NaN); // Expects an integer |
| } catch (e) {} |
| |
| try { |
| p = new TheModule.Parent(42); |
| p.voidStar(1234) // Expects a wrapped pointer |
| } catch (e) {} |
| |
| try { |
| s = new TheModule.StringUser('abc', 1); |
| s.Print(123, null); // Expects a string or a wrapped pointer |
| } catch (e) {} |
| |
| // Check for overflowing the stack |
| |
| var before = Date.now(); |
| |
| for (var i = 0; i < 1000000; i++) { |
| var temp = new TheModule.StringUser('abc', 1); |
| TheModule.destroy(temp); |
| if (Date.now() - before >= 1000) break; |
| } |
| |
| if (isMemoryGrowthAllowed) { |
| // Check for HEAP reallocation when using large arrays |
| var numArrayEntries = 100000; |
| var intArray = new Array(numArrayEntries); |
| for (var i = 0; i < numArrayEntries; i++) { |
| intArray[i] = i; |
| } |
| |
| var startHeapLength = TheModule['HEAP8'].length; |
| var offset; |
| var storeArray = new TheModule.StoreArray(); |
| storeArray.setArray(intArray); |
| // Add more data until the heap is reallocated |
| while (TheModule['HEAP8'].length === startHeapLength) { |
| intArray = intArray.concat(intArray); |
| storeArray.setArray(intArray); |
| } |
| |
| // Make sure the array was copied to the newly allocated HEAP |
| var numCopiedEntries = 0; |
| for (var i = 0; i < intArray.length; i++) { |
| if (storeArray.getArrayValue(i) !== intArray[i]) { |
| break; |
| } |
| numCopiedEntries += 1; |
| } |
| |
| if (intArray.length !== numCopiedEntries) { |
| console.log('ERROR: An array was not copied to HEAP32 after memory reallocation'); |
| } |
| } |
| |
| // |
| |
| console.log('\ndone.') |
| |