<commit_before>"use strict";
/* @flow */

const Value = require('../Value');
const PropertyDescriptor = require('./PropertyDescriptor');
const CompletionRecord = require('../CompletionRecord');
const PrimitiveValue = require('./PrimitiveValue');

/**
 * Represents a value that maps directly to an untrusted local value.
 */
class ObjectValue extends Value {
	
	constructor(realm) {
		super(realm);
		this.extensable = true;
		this.properties = Object.create(null);
		this.setPrototype(this.realm.ObjectPrototype);
	}

	ref(name) {
		var existing = this.properties[name];
		var ret = {
			set: (v,s) => this.assign(name,v,s),
		};

		let get;
		if ( existing ) {
			ret.isVariable = existing.isVariable;
			ret.del = () => {
				if ( !this.properties[name].configurable ) return false;
				delete this.properties[name];
				return true;
			};
			ret.getValue = existing.getValue.bind(existing, this);
			ret.setValue = existing.setValue.bind(existing, this);
			Object.defineProperty(ret, 'value', {
				get: () => existing.value,
				set: (v) => {
					this.assign(name, v);
				}
			});

		} else {
			ret.isVariable = false;
			ret.del = () => false;
			Object.defineProperty(ret, 'value', {
				get: () => Value.undef,
				set: (v) => {
					this.assign(name, v);
				}
			});
			ret.getValue = function *() { return Value.undef; };
			ret.setValue = function *(to) { return ret.value = to; };
		}
		return ret;
	}

	assign(name, value, s) {
		let v;
		if ( Object.prototype.hasOwnProperty.call(this.properties, name) ) {
			v = this.properties[name];
			if ( v.writeable ) {
				v.value = value;
			} else if ( s && s.strict ) {
				console.log("A");
				throw new TypeError('Cant write to something thats not writeable');
			} else {
				console.log("B");
				throw new TypeError('Not STrict!')
			}
		} else if ( this.extensable ) {
			v = new PropertyDescriptor(value, this);
			v.del = () => this.delete(name);
			this.properties[name] = v;
		} else {
			//TODO: Should we throw here in strict mode?
			return;
		}
	}

	get(name) {
		let ref = this.properties[name];
		if ( ref ) return ref.value;
		return Value.undef;
	}

	rawSetProperty(name, value) {
		this.properties[name] = value;
	}

	
	set(name, value) {
		let v;
		if ( Object.prototype.hasOwnProperty.call(this.properties, name) ) {
			v = this.properties[name];
			v.value = value;
		} else {
			v = new PropertyDescriptor(value, this);
			v.del = () => this.delete(name);
			this.properties[name] = v;
		}
	}

	has(name) {
		return name in this.properties;
	}

	delete(name) {
		delete this.properties[name];
	}
	
	toNative() {
		var bk = Value.createNativeBookmark(this);
		for ( let p in this.properties ) {
			if ( Object.prototype.hasOwnProperty.call(bk, p) ) continue;
			//TODO: Worry about getter and setter functions.
			Object.defineProperty(bk, p, {
				get: () => {
					var c = this.properties[p].value;
					return c === undefined ? undefined : c.toNative();
				},
				set: (v) => { this.properties[p].value = Value.fromNative(v, this.realm); }
			});
		}
		return bk;
	}


	*add(other) { return yield * (yield * this.toPrimitiveValue()).add(other); }
	*doubleEquals(other) {
		if ( other instanceof PrimitiveValue ) {
			let pv = yield * this.toPrimitiveValue();
			return yield * pv.doubleEquals(other);
		}
		let pthis = yield * this.toPrimitiveValue();
		return yield * pthis.doubleEquals(other);
	}
	*inOperator(str) {
		let svalue = yield * str.toStringValue();
		return this.has(svalue.toNative()) ? Value.true : Value.false;
	}

	*member(name) { 
		let ref = this.ref(name);
		if ( ref ) return yield * ref.getValue(this);
		return Value.undef;
	}

	*instanceOf(other, realm) {<commit_msg>Send better object representations to native functions.<commit_after>"use strict";
/* @flow */

const Value = require('../Value');
const PropertyDescriptor = require('./PropertyDescriptor');
const CompletionRecord = require('../CompletionRecord');
const PrimitiveValue = require('./PrimitiveValue');

/**
 * Represents a value that maps directly to an untrusted local value.
 */
class ObjectValue extends Value {
	
	constructor(realm) {
		super(realm);
		this.extensable = true;
		this.properties = Object.create(null);
		this.setPrototype(this.realm.ObjectPrototype);
	}

	ref(name) {
		var existing = this.properties[name];
		var ret = {
			set: (v,s) => this.assign(name,v,s),
		};

		let get;
		if ( existing ) {
			ret.isVariable = existing.isVariable;
			ret.del = () => {
				if ( !this.properties[name].configurable ) return false;
				delete this.properties[name];
				return true;
			};
			ret.getValue = existing.getValue.bind(existing, this);
			ret.setValue = existing.setValue.bind(existing, this);
			Object.defineProperty(ret, 'value', {
				get: () => existing.value,
				set: (v) => {
					this.assign(name, v);
				}
			});

		} else {
			ret.isVariable = false;
			ret.del = () => false;
			Object.defineProperty(ret, 'value', {
				get: () => Value.undef,
				set: (v) => {
					this.assign(name, v);
				}
			});
			ret.getValue = function *() { return Value.undef; };
			ret.setValue = function *(to) { return ret.value = to; };
		}
		return ret;
	}

	assign(name, value, s) {
		let v;
		if ( Object.prototype.hasOwnProperty.call(this.properties, name) ) {
			v = this.properties[name];
			if ( v.writeable ) {
				v.value = value;
			} else if ( s && s.strict ) {
				console.log("A");
				throw new TypeError('Cant write to something thats not writeable');
			} else {
				console.log("B");
				throw new TypeError('Not STrict!')
			}
		} else if ( this.extensable ) {
			v = new PropertyDescriptor(value, this);
			v.del = () => this.delete(name);
			this.properties[name] = v;
		} else {
			//TODO: Should we throw here in strict mode?
			return;
		}
	}

	get(name) {
		let ref = this.properties[name];
		if ( ref ) return ref.value;
		return Value.undef;
	}

	rawSetProperty(name, value) {
		this.properties[name] = value;
	}

	
	set(name, value) {
		let v;
		if ( Object.prototype.hasOwnProperty.call(this.properties, name) ) {
			v = this.properties[name];
			v.value = value;
		} else {
			v = new PropertyDescriptor(value, this);
			v.del = () => this.delete(name);
			this.properties[name] = v;
		}
	}

	has(name) {
		return name in this.properties;
	}

	delete(name) {
		delete this.properties[name];
	}
	
	toNative() {
		var bk = Value.createNativeBookmark(this);
		for ( let p in this.properties ) {
			if ( Object.prototype.hasOwnProperty.call(bk, p) ) continue;
			//TODO: Worry about getter and setter functions.
			Object.defineProperty(bk, p, {
				get: () => {
					var c = this.properties[p].value;
					return c === undefined ? undefined : c.toNative();
				},
				set: (v) => { this.properties[p].value = Value.fromNative(v, this.realm); },
				enumerable: this.properties[p].enumerable, writeable: this.properties[p].writeable, configurable: this.properties[p].configurable
			});
		}
		return bk;
	}


	*add(other) { return yield * (yield * this.toPrimitiveValue()).add(other); }
	*doubleEquals(other) {
		if ( other instanceof PrimitiveValue ) {
			let pv = yield * this.toPrimitiveValue();
			return yield * pv.doubleEquals(other);
		}
		let pthis = yield * this.toPrimitiveValue();
		return yield * pthis.doubleEquals(other);
	}
	*inOperator(str) {
		let svalue = yield * str.toStringValue();
		return this.has(svalue.toNative()) ? Value.true : Value.false;
	}

	*member(name) { 
		let ref = this.ref(name);
		if ( ref ) return yield * ref.getValue(this);
		return Value.undef;
	}

	*instanceOf(other, realm) {
{'fraction_non_alphanumeric': 0.15869017632241814, 'fraction_numerical': 0.0, 'mean_word_length': 3.2145251396648047, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5738507', 'n_tokens_mistral': 2927, 'n_tokens_neox': 2541, 'n_words': 574}