Skip to content

Commit

Permalink
Separate Wrapper class into its own file.
Browse files Browse the repository at this point in the history
  • Loading branch information
jjrv committed Oct 25, 2016
1 parent 3b1fdb4 commit 584aaf6
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 135 deletions.
137 changes: 6 additions & 131 deletions src/em/BindClass.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,19 @@
// This file is part of nbind, copyright (C) 2014-2016 BusFaster Ltd.
// Released under the MIT license, see LICENSE.

import {
setEvil,
defineHidden,
prepareNamespace
} from 'emscripten-library-decorator';

import {setEvil, prepareNamespace} from 'emscripten-library-decorator';
import {_nbind as _globals} from './Globals';
import {_nbind as _type} from './BindingType';
import {_nbind as _value} from './ValueObj';
import {_nbind as _caller} from './Caller';
import {_nbind as _wrapper} from './Wrapper';
import {_nbind as _resource} from './Resource';
import {_nbind as _gc} from './GC';
import {SignatureType} from '../common';
import {StateFlags, TypeFlags, TypeSpecWithName, TypeSpecWithParam, PolicyTbl} from '../Type';
import {TypeFlags, TypeSpecWithName, TypeSpecWithParam, PolicyTbl} from '../Type';

// Let decorators run eval in current scope to read function source code.
setEvil((code: string) => eval(code));

const _defineHidden = defineHidden;

export namespace _nbind {
export var BindType = _type.BindType;
}
Expand All @@ -38,32 +31,8 @@ export namespace _nbind {
export var makeCaller: typeof _caller.makeCaller;
export var makeMethodCaller: typeof _caller.makeMethodCaller;

export var mark: typeof _gc.mark;

/** Base class for wrapped instances of bound C++ classes.
* Note that some hacks avoid ever constructing this,
* so initializing values inside its definition won't work. */

export class Wrapper {
persist() { this.__nbindState |= StateFlags.isPersistent; }

free?(): void

/* tslint:disable:variable-name */

__nbindFlags: TypeFlags;
__nbindState: StateFlags;

/** Dynamically set by _nbind_register_constructor.
* Calls the C++ constructor and returns a numeric heap pointer. */
__nbindConstructor: (...args: any[]) => number;
__nbindValueConstructor: _globals.Func;

__nbindPtr: number;
__nbindShared: number;

/* tslint:enable:variable-name */
}
type Wrapper = _wrapper.Wrapper;
export var makeBound: typeof _wrapper.makeBound;

// Any subtype (not instance but type) of Wrapper.
// Declared as anything that constructs something compatible with Wrapper.
Expand All @@ -74,90 +43,7 @@ export namespace _nbind {
[key: string]: any;
}

const ptrMarker = {};

export function makeBound(
policyTbl: PolicyTbl,
bindClass: BindClass
) {
class Bound extends Wrapper {
constructor(marker: {}, flags: number, ptr: number, shared?: number) {
// super() never gets called here but TypeScript 1.8 requires it.
if((false && super()) || !(this instanceof Bound)) {

// Constructor called without new operator.
// Make correct call with given arguments.
// Few ways to do this work. This one should. See:
// http://stackoverflow.com/questions/1606797
// /use-of-apply-with-new-operator-is-this-possible

return(new (Function.prototype.bind.apply(
Bound, // arguments.callee
Array.prototype.concat.apply([null], arguments)
))());
}

let nbindFlags = flags;
let nbindPtr = ptr;
let nbindShared = shared;

if(marker !== ptrMarker) {
let wirePtr = this.__nbindConstructor.apply(this, arguments);

nbindFlags = TypeFlags.isSharedClassPtr | TypeFlags.isSharedPtr;
nbindShared = HEAPU32[wirePtr / 4];
nbindPtr = HEAPU32[wirePtr / 4 + 1];
}

const spec = {
configurable: true,
enumerable: false,
value: null as any,
writable: false
};

const propTbl: { [key: string]: any } = {
'__nbindFlags': nbindFlags,
'__nbindPtr': nbindPtr
};

if(nbindShared) {
propTbl['__nbindShared'] = nbindShared;
mark(this);
}

for(let key of Object.keys(propTbl)) {
spec.value = propTbl[key];
Object.defineProperty(this, key, spec);
}

_defineHidden(StateFlags.none)(this, '__nbindState');
}

free() {
bindClass.destroy.call(this, this.__nbindShared, this.__nbindFlags);

this.__nbindState |= StateFlags.isDeleted;

disableMember(this, '__nbindShared');
disableMember(this, '__nbindPtr');
}

@_defineHidden()
// tslint:disable-next-line:variable-name
__nbindConstructor: (...args: any[]) => number;

@_defineHidden()
// tslint:disable-next-line:variable-name
__nbindValueConstructor: _globals.Func;

@_defineHidden(policyTbl)
// tslint:disable-next-line:variable-name
__nbindPolicies: { [name: string]: boolean };
}

return(Bound);
}
export const ptrMarker = {};

export interface MethodSpec {
name: string;
Expand Down Expand Up @@ -415,17 +301,6 @@ export namespace _nbind {
proto: WrapperClass;
}

function disableMember(obj: Wrapper, name: string) {
function die() { throw(new Error('Accessing deleted object')); }

Object.defineProperty(obj, name, {
configurable: false,
enumerable: false,
get: die,
set: die
});
}

@prepareNamespace('_nbind')
export class _ {} // tslint:disable-line:class-name
}
3 changes: 2 additions & 1 deletion src/em/Caller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {setEvil, prepareNamespace} from 'emscripten-library-decorator';
import {_nbind as _globals} from './Globals';
import {_nbind as _type} from './BindingType';
import {_nbind as _class} from './BindClass';
import {_nbind as _wrapper} from './Wrapper';
import {_nbind as _external} from './External';
import {_nbind as _resource} from './Resource';
import {TypeFlags, PolicyTbl} from '../Type';
Expand All @@ -19,7 +20,7 @@ export namespace _nbind {

type BindType = _type.BindType;

type Wrapper = _class.Wrapper;
type Wrapper = _wrapper.Wrapper;

type Func = _globals.Func;
type FuncList = _globals.FuncList;
Expand Down
4 changes: 2 additions & 2 deletions src/em/GC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
// wrapped in type conversions for arguments and return values.

import {setEvil, prepareNamespace} from 'emscripten-library-decorator';
import {_nbind as _class} from './BindClass';
import {_nbind as _wrapper} from './Wrapper';
import {StateFlags} from '../Type';

// Let decorators run eval in current scope to read function source code.
setEvil((code: string) => eval(code));

export namespace _nbind {

type Wrapper = _class.Wrapper;
type Wrapper = _wrapper.Wrapper;

let dirtyList: Wrapper[] = [];

Expand Down
3 changes: 2 additions & 1 deletion src/em/ValueObj.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
import {_nbind as _globals} from './Globals';
import {_nbind as _type} from './BindingType';
import {_nbind as _class} from './BindClass';
import {_nbind as _wrapper} from './Wrapper';

// Let decorators run eval in current scope to read function source code.
setEvil((code: string) => eval(code));
Expand Down Expand Up @@ -62,7 +63,7 @@ export namespace _nbind {
export function popValue(
num: number,
type?: BindClassPtr
): ValueObject | _class.Wrapper | null {
): ValueObject | _wrapper.Wrapper | null {
if(!num) throwError('Value type JavaScript class is missing or not registered');

if(num & 1) {
Expand Down
147 changes: 147 additions & 0 deletions src/em/Wrapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
// This file is part of nbind, copyright (C) 2014-2016 BusFaster Ltd.
// Released under the MIT license, see LICENSE.

import {
setEvil,
defineHidden,
prepareNamespace
} from 'emscripten-library-decorator';

import {_nbind as _globals} from './Globals';
import {_nbind as _class} from './BindClass';
import {_nbind as _gc} from './GC';
import {StateFlags, TypeFlags, PolicyTbl} from '../Type';

// Let decorators run eval in current scope to read function source code.
setEvil((code: string) => eval(code));

const _defineHidden = defineHidden;

export namespace _nbind {

export var ptrMarker: typeof _class.ptrMarker;

export var mark: typeof _gc.mark;

/** Base class for wrapped instances of bound C++ classes.
* Note that some hacks avoid ever constructing this,
* so initializing values inside its definition won't work. */

export class Wrapper {
persist() { this.__nbindState |= StateFlags.isPersistent; }

free?(): void

/* tslint:disable:variable-name */

__nbindFlags: TypeFlags;
__nbindState: StateFlags;

/** Dynamically set by _nbind_register_constructor.
* Calls the C++ constructor and returns a numeric heap pointer. */
__nbindConstructor: (...args: any[]) => number;
__nbindValueConstructor: _globals.Func;

__nbindPtr: number;
__nbindShared: number;

/* tslint:enable:variable-name */
}

export function makeBound(
policyTbl: PolicyTbl,
bindClass: _class.BindClass
) {
class Bound extends Wrapper {
constructor(marker: {}, flags: number, ptr: number, shared?: number) {
// super() never gets called here but TypeScript 1.8 requires it.
if((false && super()) || !(this instanceof Bound)) {

// Constructor called without new operator.
// Make correct call with given arguments.
// Few ways to do this work. This one should. See:
// http://stackoverflow.com/questions/1606797
// /use-of-apply-with-new-operator-is-this-possible

return(new (Function.prototype.bind.apply(
Bound, // arguments.callee
Array.prototype.concat.apply([null], arguments)
))());
}

let nbindFlags = flags;
let nbindPtr = ptr;
let nbindShared = shared;

if(marker !== ptrMarker) {
let wirePtr = this.__nbindConstructor.apply(this, arguments);

nbindFlags = TypeFlags.isSharedClassPtr | TypeFlags.isSharedPtr;
nbindShared = HEAPU32[wirePtr / 4];
nbindPtr = HEAPU32[wirePtr / 4 + 1];
}

const spec = {
configurable: true,
enumerable: false,
value: null as any,
writable: false
};

const propTbl: { [key: string]: any } = {
'__nbindFlags': nbindFlags,
'__nbindPtr': nbindPtr
};

if(nbindShared) {
propTbl['__nbindShared'] = nbindShared;
mark(this);
}

for(let key of Object.keys(propTbl)) {
spec.value = propTbl[key];
Object.defineProperty(this, key, spec);
}

_defineHidden(StateFlags.none)(this, '__nbindState');
}

free() {
bindClass.destroy.call(this, this.__nbindShared, this.__nbindFlags);

this.__nbindState |= StateFlags.isDeleted;

disableMember(this, '__nbindShared');
disableMember(this, '__nbindPtr');
}

@_defineHidden()
// tslint:disable-next-line:variable-name
__nbindConstructor: (...args: any[]) => number;

@_defineHidden()
// tslint:disable-next-line:variable-name
__nbindValueConstructor: _globals.Func;

@_defineHidden(policyTbl)
// tslint:disable-next-line:variable-name
__nbindPolicies: { [name: string]: boolean };
}

return(Bound);
}

function disableMember(obj: Wrapper, name: string) {
function die() { throw(new Error('Accessing deleted object')); }

Object.defineProperty(obj, name, {
configurable: false,
enumerable: false,
get: die,
set: die
});
}

@prepareNamespace('_nbind')
export class _ {} // tslint:disable-line:class-name
}
1 change: 1 addition & 0 deletions src/em/em-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { _nbind as _callback } from './Callback'; export { _callback };
import { _nbind as _value } from './ValueObj'; export { _value };
import { _nbind as _std } from './BindingStd'; export { _std };
import { _nbind as _caller } from './Caller'; export { _caller };
import { _nbind as _wrapper } from './Wrapper'; export { _wrapper };
import { _nbind as _resource } from './Resource'; export { _resource };
import { _nbind as _buffer } from './Buffer'; export { _buffer };
import { _nbind as _gc } from './GC'; export { _gc };
Expand Down

0 comments on commit 584aaf6

Please sign in to comment.