src/values/BridgeValue.js
'use strict';
/* @flow */
const Value = require('../Value');
const CompletionRecord = require('../CompletionRecord');
/**
* Represents a value that maps directly to an untrusted local value.
*/
class BridgeValue extends Value {
constructor(value) {
super();
this.native = value;
}
makeBridge(value) {
return BridgeValue.make(value);
}
static make(native) {
if ( native === undefined ) return Value.undef;
let prim = Value.fromPrimativeNative(native);
if ( prim ) return prim;
if ( Value.hasBookmark(native) ) {
return Value.getBookmark(native);
}
return new BridgeValue(native);
}
ref(name, s) {
let that = this;
let out = Object.create(null);
let doset = (value) => that.native[name] = value.toNative();
out.getValue = function *() { return Value.fromNative(that.native[name]); };
out.setValue = function *(to) { doset(to) };
return out;
}
toNative() {
return this.native;
}
*asString() {
return this.native.toString();
}
*doubleEquals(other) { return this.makeBridge(this.native == other.toNative()); }
*tripleEquals(other) { return this.makeBridge(this.native === other.toNative()); }
*add(other) { return this.makeBridge(this.native + other.toNative()); }
*subtract(other) { return this.makeBridge(this.native - other.toNative()); }
*multiply(other) { return this.makeBridge(this.native * other.toNative()); }
*divide(other) { return this.makeBridge(this.native / other.toNative()); }
*mod(other) { return this.makeBridge(this.native % other.toNative()); }
*shiftLeft(other) { return this.makeBridge(this.native << other.toNative()); }
*shiftRight(other) { return this.makeBridge(this.native >> other.toNative()); }
*shiftRightZF(other) { return this.makeBridge(this.native >>> other.toNative()); }
*bitAnd(other) { return this.makeBridge(this.native & other.toNative()); }
*bitOr(other) { return this.makeBridge(this.native | other.toNative()); }
*bitXor(other) { return this.makeBridge(this.native ^ other.toNative()); }
*gt(other) { return this.makeBridge(this.native > other.toNative()); }
*lt(other) { return this.makeBridge(this.native < other.toNative()); }
*gte(other) { return this.makeBridge(this.native >= other.toNative()); }
*lte(other) { return this.makeBridge(this.native <= other.toNative()); }
*inOperator(other) { return this.makeBridge(other.toNative() in this.native); }
*instanceOf(other) { return this.makeBridge(this.native instanceof other.toNative()); }
*unaryPlus() { return this.makeBridge(+this.native); }
*unaryMinus() { return this.makeBridge(-this.native); }
*not() { return this.makeBridge(!this.native); }
*get(name) {
return this.makeBridge(this.native[name]);
}
*set(name, value) {
this.native[name] = value.toNative();
}
*observableProperties(realm) {
for ( let p in this.native ) {
yield this.makeBridge(p);
}
return;
}
/**
*
* @param {Value} thiz
* @param {Value[]} args
*/
*call(thiz, args) {
let realArgs = new Array(args.length);
for ( let i = 0; i < args.length; ++i ) {
realArgs[i] = args[i].toNative();
}
try {
let result = this.native.apply(thiz ? thiz.toNative() : undefined, realArgs);
return this.makeBridge(result);
} catch ( e ) {
let result = this.makeBridge(e);
return new CompletionRecord(CompletionRecord.THROW, result);
}
}
*makeThisForNew() {
return this.makeBridge(Object.create(this.native.prototype));
}
*toStringValue() { return this.fromNative(this.native.toString()); }
get debugString() {
return '[Bridge: ' + this.native + ']';
}
get truthy() {
return !!this.native;
}
get jsTypeName() {
return typeof this.native;
}
}
module.exports = BridgeValue;