Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
219 changed files
with
299,681 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
203 changes: 203 additions & 0 deletions
203
ember-vendored-pr-19806/dependencies/@glimmer/destroyable.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,203 @@ | ||
import { DEBUG } from '@glimmer/env'; | ||
import { debugToString } from '@glimmer/util'; | ||
import { scheduleDestroy, scheduleDestroyed } from '@glimmer/global-context'; | ||
|
||
let DESTROYABLE_META = new WeakMap(); | ||
|
||
function push(collection, newItem) { | ||
if (collection === null) { | ||
return newItem; | ||
} else if (Array.isArray(collection)) { | ||
collection.push(newItem); | ||
return collection; | ||
} else { | ||
return [collection, newItem]; | ||
} | ||
} | ||
|
||
function iterate(collection, fn) { | ||
if (Array.isArray(collection)) { | ||
for (let i = 0; i < collection.length; i++) { | ||
fn(collection[i]); | ||
} | ||
} else if (collection !== null) { | ||
fn(collection); | ||
} | ||
} | ||
|
||
function remove(collection, item, message) { | ||
if (DEBUG) { | ||
let collectionIsItem = collection === item; | ||
let collectionContainsItem = Array.isArray(collection) && collection.indexOf(item) !== -1; | ||
|
||
if (!collectionIsItem && !collectionContainsItem) { | ||
throw new Error(String(message)); | ||
} | ||
} | ||
|
||
if (Array.isArray(collection) && collection.length > 1) { | ||
let index = collection.indexOf(item); | ||
collection.splice(index, 1); | ||
return collection; | ||
} else { | ||
return null; | ||
} | ||
} | ||
|
||
function getDestroyableMeta(destroyable) { | ||
let meta = DESTROYABLE_META.get(destroyable); | ||
|
||
if (meta === undefined) { | ||
meta = { | ||
parents: null, | ||
children: null, | ||
eagerDestructors: null, | ||
destructors: null, | ||
state: 0 | ||
/* Live */ | ||
|
||
}; | ||
|
||
if (DEBUG) { | ||
meta.source = destroyable; | ||
} | ||
|
||
DESTROYABLE_META.set(destroyable, meta); | ||
} | ||
|
||
return meta; | ||
} | ||
|
||
function associateDestroyableChild(parent, child) { | ||
if (DEBUG && isDestroying(parent)) { | ||
throw new Error('Attempted to associate a destroyable child with an object that is already destroying or destroyed'); | ||
} | ||
|
||
let parentMeta = getDestroyableMeta(parent); | ||
let childMeta = getDestroyableMeta(child); | ||
parentMeta.children = push(parentMeta.children, child); | ||
childMeta.parents = push(childMeta.parents, parent); | ||
return child; | ||
} | ||
function registerDestructor(destroyable, destructor, eager = false) { | ||
if (DEBUG && isDestroying(destroyable)) { | ||
throw new Error('Attempted to register a destructor with an object that is already destroying or destroyed'); | ||
} | ||
|
||
let meta = getDestroyableMeta(destroyable); | ||
let destructorsKey = eager === true ? 'eagerDestructors' : 'destructors'; | ||
meta[destructorsKey] = push(meta[destructorsKey], destructor); | ||
return destructor; | ||
} | ||
function unregisterDestructor(destroyable, destructor, eager = false) { | ||
if (DEBUG && isDestroying(destroyable)) { | ||
throw new Error('Attempted to unregister a destructor with an object that is already destroying or destroyed'); | ||
} | ||
|
||
let meta = getDestroyableMeta(destroyable); | ||
let destructorsKey = eager === true ? 'eagerDestructors' : 'destructors'; | ||
meta[destructorsKey] = remove(meta[destructorsKey], destructor, DEBUG && 'attempted to remove a destructor that was not registered with the destroyable'); | ||
} //////////// | ||
|
||
function destroy(destroyable) { | ||
let meta = getDestroyableMeta(destroyable); | ||
if (meta.state >= 1 | ||
/* Destroying */ | ||
) return; | ||
let { | ||
parents, | ||
children, | ||
eagerDestructors, | ||
destructors | ||
} = meta; | ||
meta.state = 1 | ||
/* Destroying */ | ||
; | ||
iterate(children, destroy); | ||
iterate(eagerDestructors, destructor => destructor(destroyable)); | ||
iterate(destructors, destructor => scheduleDestroy(destroyable, destructor)); | ||
scheduleDestroyed(() => { | ||
iterate(parents, parent => removeChildFromParent(destroyable, parent)); | ||
meta.state = 2 | ||
/* Destroyed */ | ||
; | ||
}); | ||
} | ||
|
||
function removeChildFromParent(child, parent) { | ||
let parentMeta = getDestroyableMeta(parent); | ||
|
||
if (parentMeta.state === 0 | ||
/* Live */ | ||
) { | ||
parentMeta.children = remove(parentMeta.children, child, DEBUG && "attempted to remove child from parent, but the parent's children did not contain the child. This is likely a bug with destructors."); | ||
} | ||
} | ||
|
||
function destroyChildren(destroyable) { | ||
let { | ||
children | ||
} = getDestroyableMeta(destroyable); | ||
iterate(children, destroy); | ||
} | ||
function _hasDestroyableChildren(destroyable) { | ||
let meta = DESTROYABLE_META.get(destroyable); | ||
return meta === undefined ? false : meta.children !== null; | ||
} | ||
function isDestroying(destroyable) { | ||
let meta = DESTROYABLE_META.get(destroyable); | ||
return meta === undefined ? false : meta.state >= 1 | ||
/* Destroying */ | ||
; | ||
} | ||
function isDestroyed(destroyable) { | ||
let meta = DESTROYABLE_META.get(destroyable); | ||
return meta === undefined ? false : meta.state >= 2 | ||
/* Destroyed */ | ||
; | ||
} //////////// | ||
|
||
let enableDestroyableTracking; | ||
let assertDestroyablesDestroyed; | ||
|
||
if (DEBUG) { | ||
let isTesting = false; | ||
|
||
enableDestroyableTracking = () => { | ||
if (isTesting) { | ||
// Reset destroyable meta just in case, before throwing the error | ||
DESTROYABLE_META = new WeakMap(); | ||
throw new Error('Attempted to start destroyable testing, but you did not end the previous destroyable test. Did you forget to call `assertDestroyablesDestroyed()`'); | ||
} | ||
|
||
isTesting = true; | ||
DESTROYABLE_META = new Map(); | ||
}; | ||
|
||
assertDestroyablesDestroyed = () => { | ||
if (!isTesting) { | ||
throw new Error('Attempted to assert destroyables destroyed, but you did not start a destroyable test. Did you forget to call `enableDestroyableTracking()`'); | ||
} | ||
|
||
isTesting = false; | ||
let map = DESTROYABLE_META; | ||
DESTROYABLE_META = new WeakMap(); | ||
let undestroyed = []; | ||
map.forEach(meta => { | ||
if (meta.state !== 2 | ||
/* Destroyed */ | ||
) { | ||
undestroyed.push(meta.source); | ||
} | ||
}); | ||
|
||
if (undestroyed.length > 0) { | ||
let objectsToString = undestroyed.map(debugToString).join('\n '); | ||
let error = new Error(`Some destroyables were not destroyed during this test:\n ${objectsToString}`); | ||
error.destroyables = undestroyed; | ||
throw error; | ||
} | ||
}; | ||
} | ||
|
||
export { associateDestroyableChild, registerDestructor, unregisterDestructor, destroy, destroyChildren, _hasDestroyableChildren, isDestroying, isDestroyed, enableDestroyableTracking, assertDestroyablesDestroyed }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import { DEBUG } from '@glimmer/env'; | ||
|
||
class InstructionEncoderImpl { | ||
constructor(buffer) { | ||
this.buffer = buffer; | ||
this.size = 0; | ||
} | ||
|
||
encode(type, machine) { | ||
if (type > 255 | ||
/* TYPE_SIZE */ | ||
) { | ||
throw new Error(`Opcode type over 8-bits. Got ${type}.`); | ||
} | ||
|
||
let first = type | machine | arguments.length - 2 << 8 | ||
/* ARG_SHIFT */ | ||
; | ||
this.buffer.push(first); | ||
|
||
for (let i = 2; i < arguments.length; i++) { | ||
let op = arguments[i]; | ||
|
||
if (DEBUG && typeof op === 'number' && op > 2147483647 | ||
/* MAX_SIZE */ | ||
) { | ||
throw new Error(`Operand over 32-bits. Got ${op}.`); | ||
} | ||
|
||
this.buffer.push(op); | ||
} | ||
|
||
this.size = this.buffer.length; | ||
} | ||
|
||
patch(position, target) { | ||
if (this.buffer[position + 1] === -1) { | ||
this.buffer[position + 1] = target; | ||
} else { | ||
throw new Error('Trying to patch operand in populated slot instead of a reserved slot.'); | ||
} | ||
} | ||
|
||
} | ||
|
||
export { InstructionEncoderImpl }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
const DEBUG = false; | ||
const CI = false; | ||
|
||
export { DEBUG, CI }; |
Oops, something went wrong.