Skip to content

Commit

Permalink
refactor(SymbolShim): export SymbolShim using factory
Browse files Browse the repository at this point in the history
  • Loading branch information
kwonoj committed Dec 3, 2015
1 parent dee84a3 commit 2c5bf41
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 37 deletions.
102 changes: 102 additions & 0 deletions spec/util/SymbolShim-spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/* globals __root__ */
var SymbolDefinition = require('../../dist/cjs/util/SymbolShim').SymbolDefinition;
var Map = require('../../dist/cjs/util/Map').Map;
var Rx = require('../../dist/cjs/Rx');

describe('SymbolDefinition', function () {
it('should setup symbol if root does not have it', function () {
var root = {};

var result = new SymbolDefinition(root);
expect(root.Symbol).toBeDefined();
expect(result.observable).toBeDefined();
expect(result.iterator).toBeDefined();
});

it('should have observable, iterator symbols', function () {
var result = new SymbolDefinition(__root__);

expect(typeof result.observable).toBe('symbol');
expect(typeof result.iterator).toBe('symbol');
});

describe('when symbols exists on root', function () {
it('should use symbols from root', function () {
var root = {
Symbol: {
observable: {},
iterator: {}
}
};

var result = new SymbolDefinition(root);
expect(result.observable).toBe(root.Symbol.observable);
expect(result.iterator).toBe(root.Symbol.iterator);
});
});

describe('observable symbol', function () {
it('should patch root using for symbol if exist', function () {
var root = {
Symbol: {
for: function (x) { return x; }
}
};

var result = new SymbolDefinition(root);
expect(result.observable).toBe(root.Symbol.for('observable'));
});

it('should patch root if for symbol does not exist', function () {
var root = {};

var result = new SymbolDefinition(root);
expect(result.observable).toBe('@@observable');
});
});

describe('iterator symbol', function () {
it('should patch root using for symbol if exist', function () {
var root = {
Symbol: {
for: function (x) { return x; }
}
};

var result = new SymbolDefinition(root);
expect(result.iterator).toBe(root.Symbol.for('iterator'));
});

it('should patch root if for symbol does not exist', function () {
var root = {};

var result = new SymbolDefinition(root);
expect(result.iterator).toBe('@@iterator');
});

it('should patch using set for mozilla', function () {
var root = {
Set: function () {
var ret = {};
ret['@@iterator'] = function () {};
return ret;
}
};

var result = new SymbolDefinition(root);
expect(result.iterator).toBe('@@iterator');
});

it('should patch using map for es6-shim', function () {
var root = {
Map: Map
};

root.Map.prototype.key = 'iteratorValue';
root.Map.prototype.entries = 'iteratorValue';

var result = new SymbolDefinition(root);
expect(result.iterator).toBe('key');
});
});
});
83 changes: 46 additions & 37 deletions src/util/SymbolShim.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,57 @@
import {root} from './root';

if (!root.Symbol) {
root.Symbol = {};
}
export class SymbolDefinition {
observable: symbol = null;
iterator: symbol = null;

private applyObservable(): symbol {
const root = this.root;

if (!root.Symbol.observable) {
if (typeof root.Symbol.for === 'function') {
root.Symbol.observable = root.Symbol.for('observable');
} else {
root.Symbol.observable = '@@observable';
}
}

if (!root.Symbol.observable) {
if (typeof root.Symbol.for === 'function') {
root.Symbol.observable = root.Symbol.for('observable');
} else {
root.Symbol.observable = '@@observable';
return root.Symbol.observable;
}
}

if (!root.Symbol.iterator) {
if (typeof root.Symbol.for === 'function') {
root.Symbol.iterator = root.Symbol.for('iterator');
} else if (root.Set && typeof new root.Set()['@@iterator'] === 'function') {
// Bug for mozilla version
root.Symbol.iterator = '@@iterator';
} else if (root.Map) {
// es6-shim specific logic
let keys = Object.getOwnPropertyNames(root.Map.prototype);
for (let i = 0; i < keys.length; ++i) {
let key = keys[i];
if (key !== 'entries' && key !== 'size' && root.Map.prototype[key] === root.Map.prototype['entries']) {
root.Symbol.iterator = key;
break;
private applyIterator(): symbol {
const root = this.root;

if (!root.Symbol.iterator) {
if (typeof root.Symbol.for === 'function') {
root.Symbol.iterator = root.Symbol.for('iterator');
} else if (root.Set && typeof new root.Set()['@@iterator'] === 'function') {
// Bug for mozilla version
root.Symbol.iterator = '@@iterator';
} else if (root.Map) {
// es6-shim specific logic
let keys = Object.getOwnPropertyNames(root.Map.prototype);
for (let i = 0; i < keys.length; ++i) {
let key = keys[i];
if (key !== 'entries' && key !== 'size' && root.Map.prototype[key] === root.Map.prototype['entries']) {
root.Symbol.iterator = key;
break;
}
}
} else {
root.Symbol.iterator = '@@iterator';
}
}
} else {
root.Symbol.iterator = '@@iterator';

return root.Symbol.iterator;
}
}

if (!root.Symbol.dispose) {
if (typeof root.Symbol.for === 'function') {
root.Symbol.dispose = root.Symbol.for('dispose');
} else {
root.Symbol.dispose = '@@dispose';
constructor(private root: any) {
if (!root.Symbol) {
root.Symbol = {};
}

this.observable = this.applyObservable();
this.iterator = this.applyIterator();
}
}

export module SymbolShim {
export const observable: symbol = root.Symbol.observable;
export const iterator: symbol = root.Symbol.iterator;
export const dispose: symbol = root.Symbol.dispose;
};
export const SymbolShim = new SymbolDefinition(root);

0 comments on commit 2c5bf41

Please sign in to comment.