diff --git a/lib/union.js b/lib/union.js index 5f207ac..5ee6726 100644 --- a/lib/union.js +++ b/lib/union.js @@ -64,7 +64,7 @@ function Union () { UnionType.defineProperty = defineProperty UnionType.toString = toString - UnionType.fields = {} + UnionType.allFields = {} // comply with ref's "type" interface UnionType.size = 0 @@ -73,7 +73,7 @@ function Union () { UnionType.get = get UnionType.set = set - // Read the fields list + // Read the allFields list var arg = arguments[0] if (typeof arg === 'object') { Object.keys(arg).forEach(function (name) { @@ -102,7 +102,7 @@ function set (buffer, offset, value) { var isUnion = value instanceof this if (isUnion) { // TODO: optimize - use Buffer#copy() - Object.keys(this.fields).forEach(function (name) { + Object.keys(this.allFields).forEach(function (name) { // hopefully hit the setters union[name] = value[name] }) @@ -151,7 +151,7 @@ function defineProperty (name, type) { var field = { type: type } - this.fields[name] = field + this.allFields[name] = field // calculate the new size and alignment recalc(this); @@ -168,33 +168,34 @@ function defineProperty (name, type) { } function recalc (union) { - // reset size and alignment - union.size = 0 - union.alignment = 0 + var biggest + var fieldNames = Object.keys(union.allFields) - var fieldNames = Object.keys(union.fields) - - // loop through to set the size of the union of the largest member field - // and the alignment to the requirements of the largest member + // find the largest member field by size / alignment fieldNames.forEach(function (name) { - var field = union.fields[name] + var field = union.allFields[name] var type = field.type - + var size = type.indirection === 1 ? type.size : ref.sizeof.pointer var alignment = type.alignment || ref.alignof.pointer if (type.indirection > 1) { alignment = ref.alignof.pointer } - union.alignment = Math.max(union.alignment, alignment) - union.size = Math.max(union.size, size) + var fields = {} + fields[name] = { type: type } + + var current = { fields: fields, size: size, alignment: alignment } + + if (!biggest || size > biggest.size || alignment > biggest.alignment) { + biggest = current + } }) - // any padding - var left = union.size % union.alignment - if (left > 0) { - debug('additional padding to the end of union:', union.alignment - left) - union.size += union.alignment - left - } + union.alignment = biggest.alignment; + union.size = biggest.size; + // Pretend like we only have this one field so that + // ffi-napi doesn't overcount the size + union.fields = biggest.fields; } diff --git a/package-lock.json b/package-lock.json index 269e09a..a3b31a0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,18 +1,18 @@ { "name": "@napi-ffi/ref-union-di", - "version": "1.0.1", + "version": "1.0.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@napi-ffi/ref-union-di", - "version": "1.0.1", + "version": "1.0.2", "license": "MIT", "dependencies": { "debug": "^4.3.7" }, "devDependencies": { - "@napi-ffi/ref-napi": "^3.0.5", + "@napi-ffi/ref-napi": "^3.0.7", "@napi-ffi/ref-struct-di": "^1.1.1", "mocha": "^7.1.1", "node-addon-api": "^8.2.1", @@ -426,9 +426,9 @@ } }, "node_modules/@napi-ffi/ref-napi": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@napi-ffi/ref-napi/-/ref-napi-3.0.5.tgz", - "integrity": "sha512-Oxmr7OUyZpEu0m3eEjHuTOPqnDmAPZPAZcLAfhxhKf7a2mQV2/t0DwCMgx+QDpZLBiFZRHy7oba9fvWEXS469w==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@napi-ffi/ref-napi/-/ref-napi-3.0.7.tgz", + "integrity": "sha512-oCaKehZERf2mEnqTJnxv/2hNDT5CpCH3s4jqncbi8jfSp40ydjhWk/xkuBz3GuSoCWeMW2y3EvFQS+sNDrfnug==", "dev": true, "hasInstallScript": true, "license": "MIT", diff --git a/package.json b/package.json index 6f3c3bb..b3ceaf3 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "c++", "ffi" ], - "version": "1.0.1", + "version": "1.0.2", "author": "Anna Henningsen ", "contributors": [ "Nathan Rajlich " @@ -34,7 +34,7 @@ "node-gyp-build": "^4.2.1", "mocha": "^7.1.1", "nyc": "^15.0.0", - "@napi-ffi/ref-napi": "^3.0.5", + "@napi-ffi/ref-napi": "^3.0.7", "@napi-ffi/ref-struct-di": "^1.1.1" } } diff --git a/test/union.js b/test/union.js index c664c65..0224c42 100644 --- a/test/union.js +++ b/test/union.js @@ -51,9 +51,9 @@ describe('Union', function () { , 'sval': 'string' }) - assert.strictEqual(ref.types.int, U.fields.ival.type) - assert.strictEqual(ref.types.long, U.fields.lval.type) - assert.strictEqual(ref.coerceType('string'), U.fields.sval.type) + assert.strictEqual(ref.types.int, U.allFields.ival.type) + assert.strictEqual(ref.types.long, U.allFields.lval.type) + assert.strictEqual(ref.coerceType('string'), U.allFields.sval.type) }) }) @@ -86,7 +86,7 @@ describe('Union', function () { assert.equal(expectedAlignment, unionType.alignment, 'test' + testNumber + ': __alignof__(): expected ' + unionType.alignment + ' to equal ' + expectedAlignment) }) - Object.keys(unionType.fields).forEach(function (name) { + Object.keys(unionType.allFields).forEach(function (name) { if ('skip' == name) return; // these tests just verify the assumption that the // offset of every field is always 0