定义包装类的基本属性
Object.defineProperties(Wrapper.prototype, {
$new: {
enumerable: true,
get () {
return this.$getCtor('allocAndInit');
}
},
$alloc: {
enumerable: true,
value () {
const env = vm.getEnv();
const h = this.$borrowClassHandle(env);
try {
const obj = env.allocObject(h.value);
const factory = this.$f;
return factory.cast(obj, this);
} finally {
h.unref(env);
}
}
},
$init: {
enumerable: true,
get () {
return this.$getCtor('initOnly');
}
},
$dispose: {
enumerable: true,
value () {
const ref = this.$r;
if (ref !== null) {
this.$r = null;
Script.unbindWeak(ref);
}
if (this.$h !== null) {
this.$h = undefined;
}
}
},
$clone: {
value (env) {
const C = this.$C;
return new C(this.$h, this.$t, env);
}
},
class: {
enumerable: true,
get () {
const env = vm.getEnv();
const h = this.$borrowClassHandle(env);
try {
const factory = this.$f;
return factory.cast(h.value, factory.use('java.lang.Class'));
} finally {
h.unref(env);
}
}
},
$className: {
enumerable: true,
get () {
const handle = this.$h;
if (handle === null) {
return this.$n;
}
return vm.getEnv().getObjectClassName(handle);
}
},
$ownMembers: {
enumerable: true,
get () {
const model = this.$l;
return model.list();
}
},
$super: {
enumerable: true,
get () {
const env = vm.getEnv();
const C = this.$s.$C;
return new C(this.$h, STRATEGY_DIRECT, env);
}
},
$s: {
get () {
const proto = Object.getPrototypeOf(this);
let superWrapper = proto.$_s;
if (superWrapper === undefined) {
const env = vm.getEnv();
const h = this.$borrowClassHandle(env);
try {
const superHandle = env.getSuperclass(h.value);
if (!superHandle.isNull()) {
try {
const superClassName = env.getClassName(superHandle);
const factory = proto.$f;
superWrapper = factory._getUsedClass(superClassName);
if (superWrapper === undefined) {
try {
const getSuperClassHandle = makeSuperHandleGetter(this);
superWrapper = factory._make(superClassName, getSuperClassHandle, env);
} finally {
factory._setUsedClass(superClassName, superWrapper);
}
}
} finally {
env.deleteLocalRef(superHandle);
}
} else {
superWrapper = null;
}
} finally {
h.unref(env);
}
proto.$_s = superWrapper;
}
return superWrapper;
}
},
$isSameObject: {
value (obj) {
const env = vm.getEnv();
return env.isSameObject(obj.$h, this.$h);
}
},
$getCtor: {
value (type) {
const slot = this.$c;
let ctor = slot[0];
if (ctor === null) {
const env = vm.getEnv();
const h = this.$borrowClassHandle(env);
try {
ctor = makeConstructor(h.value, this.$w, env);
slot[0] = ctor;
} finally {
h.unref(env);
}
}
return ctor[type];
}
},
$borrowClassHandle: {
value (env) {
const className = this.$n;
const classHandles = this.$f._classHandles;
let handle = classHandles.get(className);
if (handle === undefined) {
handle = new ClassHandle(this.$gch(env), env);
classHandles.set(className, handle, env);
}
return handle.ref();
}
},
$copyClassHandle: {
value (env) {
const h = this.$borrowClassHandle(env);
try {
return env.newLocalRef(h.value);
} finally {
h.unref(env);
}
}
},
$getHandle: {
value (env) {
const handle = this.$h;
const isDisposed = handle === undefined;
if (isDisposed) {
throw new Error('Wrapper is disposed; perhaps it was borrowed from a hook ' +
'instead of calling Java.retain() to make a long-lived wrapper?');
}
return handle;
}
},
$list: {
value () {
const superWrapper = this.$s;
const superMembers = (superWrapper !== null) ? superWrapper.$list() : [];
const model = this.$l;
return Array.from(new Set(superMembers.concat(model.list())));
}
},
$has: {
value (member) {
const members = this.$m;
if (members.has(member)) {
return true;
}
const model = this.$l;
if (model.has(member)) {
return true;
}
const superWrapper = this.$s;
if (superWrapper !== null && superWrapper.$has(member)) {
return true;
}
return false;
}
},
$find: {
value (member) {
const members = this.$m;
let value = members.get(member);
if (value !== undefined) {
return value;
}
const model = this.$l;
const spec = model.find(member);
if (spec !== null) {
const env = vm.getEnv();
const h = this.$borrowClassHandle(env);
try {
value = makeMember(member, spec, h.value, this.$w, env);
} finally {
h.unref(env);
}
members.set(member, value);
return value;
}
const superWrapper = this.$s;
if (superWrapper !== null) {
return superWrapper.$find(member);
}
return null;
}
},
toJSON: {
value () {
const wrapperName = this.$n;
const handle = this.$h;
if (handle === null) {
return `<class: ${wrapperName}>`;
}
const actualName = this.$className;
if (wrapperName === actualName) {
return `<instance: ${wrapperName}>`;
}
return `<instance: ${wrapperName}, $className: ${actualName}>`;
}
}
});
要创建类时,在对相关的成员变量赋值
_make (name, getClassHandle, env) {
const C = makeClassWrapperConstructor();
const proto = Object.create(Wrapper.prototype, {
$n: {
value: name
},
$C: {
value: C
},
$w: {
value: null,
writable: true
},
$_s: {
writable: true
},
$c: {
value: [null]
},
$m: {
value: new Map()
},
$l: {
value: null,
writable: true
},
$gch: {
value: getClassHandle
},
$f: {
value: this
}
});
C.prototype = proto;
const classWrapper = new C(null);
proto.$w = classWrapper;
const h = classWrapper.$borrowClassHandle(env);
try {
const classHandle = h.value;
ensureClassInitialized(env, classHandle);
proto.$l = ClassModel.build(classHandle, env);
} finally {
h.unref(env);
}
return classWrapper;
}