@bikeshaving/crank
Advanced tools
Comparing version 0.4.3 to 0.4.4
330
crank.js
@@ -958,9 +958,166 @@ /// <reference types="crank.d.ts" /> | ||
addEventListener(type, listener, options) { | ||
return addEventListener(this[$ContextImpl], type, listener, options); | ||
const impl = this[$ContextImpl]; | ||
let listeners; | ||
if (!isListenerOrListenerObject(listener)) { | ||
return; | ||
} | ||
else { | ||
const listeners1 = listenersMap.get(impl); | ||
if (listeners1) { | ||
listeners = listeners1; | ||
} | ||
else { | ||
listeners = []; | ||
listenersMap.set(impl, listeners); | ||
} | ||
} | ||
options = normalizeListenerOptions(options); | ||
let callback; | ||
if (typeof listener === "object") { | ||
callback = () => listener.handleEvent.apply(listener, arguments); | ||
} | ||
else { | ||
callback = listener; | ||
} | ||
const record = { type, callback, listener, options }; | ||
if (options.once) { | ||
record.callback = function () { | ||
const i = listeners.indexOf(record); | ||
if (i !== -1) { | ||
listeners.splice(i, 1); | ||
} | ||
return callback.apply(this, arguments); | ||
}; | ||
} | ||
if (listeners.some((record1) => record.type === record1.type && | ||
record.listener === record1.listener && | ||
!record.options.capture === !record1.options.capture)) { | ||
return; | ||
} | ||
listeners.push(record); | ||
// TODO: is it possible to separate out the EventTarget delegation logic | ||
for (const value of getChildValues(impl.ret)) { | ||
if (isEventTarget(value)) { | ||
value.addEventListener(record.type, record.callback, record.options); | ||
} | ||
} | ||
} | ||
removeEventListener(type, listener, options) { | ||
return removeEventListener(this[$ContextImpl], type, listener, options); | ||
const impl = this[$ContextImpl]; | ||
const listeners = listenersMap.get(impl); | ||
if (listeners == null || !isListenerOrListenerObject(listener)) { | ||
return; | ||
} | ||
const options1 = normalizeListenerOptions(options); | ||
const i = listeners.findIndex((record) => record.type === type && | ||
record.listener === listener && | ||
!record.options.capture === !options1.capture); | ||
if (i === -1) { | ||
return; | ||
} | ||
const record = listeners[i]; | ||
listeners.splice(i, 1); | ||
// TODO: is it possible to separate out the EventTarget delegation logic | ||
for (const value of getChildValues(impl.ret)) { | ||
if (isEventTarget(value)) { | ||
value.removeEventListener(record.type, record.callback, record.options); | ||
} | ||
} | ||
} | ||
dispatchEvent(ev) { | ||
return dispatchEvent(this[$ContextImpl], ev); | ||
const impl = this[$ContextImpl]; | ||
const path = []; | ||
for (let parent = impl.parent; parent !== undefined; parent = parent.parent) { | ||
path.push(parent); | ||
} | ||
// We patch the stopImmediatePropagation method because ev.cancelBubble | ||
// only informs us if stopPropagation was called and there are no | ||
// properties which inform us if stopImmediatePropagation was called. | ||
let immediateCancelBubble = false; | ||
const stopImmediatePropagation = ev.stopImmediatePropagation; | ||
setEventProperty(ev, "stopImmediatePropagation", () => { | ||
immediateCancelBubble = true; | ||
return stopImmediatePropagation.call(ev); | ||
}); | ||
setEventProperty(ev, "target", impl.ctx); | ||
// The only possible errors in this block are errors thrown by callbacks, | ||
// and dispatchEvent will only log these errors rather than throwing | ||
// them. Therefore, we place all code in a try block, log errors in the | ||
// catch block, and use an unsafe return statement in the finally block. | ||
// | ||
// Each early return within the try block returns true because while the | ||
// return value is overridden in the finally block, TypeScript | ||
// (justifiably) does not recognize the unsafe return statement. | ||
// | ||
// TODO: Run all callbacks even if one of them errors | ||
try { | ||
setEventProperty(ev, "eventPhase", CAPTURING_PHASE); | ||
for (let i = path.length - 1; i >= 0; i--) { | ||
const target = path[i]; | ||
const listeners = listenersMap.get(target); | ||
if (listeners) { | ||
setEventProperty(ev, "currentTarget", target.ctx); | ||
for (const record of listeners) { | ||
if (record.type === ev.type && record.options.capture) { | ||
record.callback.call(target.ctx, ev); | ||
if (immediateCancelBubble) { | ||
return true; | ||
} | ||
} | ||
} | ||
} | ||
if (ev.cancelBubble) { | ||
return true; | ||
} | ||
} | ||
{ | ||
const listeners = listenersMap.get(impl); | ||
if (listeners) { | ||
setEventProperty(ev, "eventPhase", AT_TARGET); | ||
setEventProperty(ev, "currentTarget", impl.ctx); | ||
for (const record of listeners) { | ||
if (record.type === ev.type) { | ||
record.callback.call(impl.ctx, ev); | ||
if (immediateCancelBubble) { | ||
return true; | ||
} | ||
} | ||
} | ||
if (ev.cancelBubble) { | ||
return true; | ||
} | ||
} | ||
} | ||
if (ev.bubbles) { | ||
setEventProperty(ev, "eventPhase", BUBBLING_PHASE); | ||
for (let i = 0; i < path.length; i++) { | ||
const target = path[i]; | ||
const listeners = listenersMap.get(target); | ||
if (listeners) { | ||
setEventProperty(ev, "currentTarget", target.ctx); | ||
for (const record of listeners) { | ||
if (record.type === ev.type && !record.options.capture) { | ||
record.callback.call(target.ctx, ev); | ||
if (immediateCancelBubble) { | ||
return true; | ||
} | ||
} | ||
} | ||
} | ||
if (ev.cancelBubble) { | ||
return true; | ||
} | ||
} | ||
} | ||
} | ||
catch (err) { | ||
// TODO: Use setTimeout to rethrow the error. | ||
console.error(err); | ||
} | ||
finally { | ||
setEventProperty(ev, "eventPhase", NONE); | ||
setEventProperty(ev, "currentTarget", null); | ||
// eslint-disable-next-line no-unsafe-finally | ||
return !ev.defaultPrevented; | ||
} | ||
} | ||
@@ -1366,165 +1523,8 @@ } | ||
const listenersMap = new WeakMap(); | ||
function addEventListener(ctx, type, listener, options) { | ||
let listeners; | ||
if (listener == null) { | ||
return; | ||
} | ||
else { | ||
const listeners1 = listenersMap.get(ctx); | ||
if (listeners1) { | ||
listeners = listeners1; | ||
} | ||
else { | ||
listeners = []; | ||
listenersMap.set(ctx, listeners); | ||
} | ||
} | ||
options = normalizeListenerOptions(options); | ||
let callback; | ||
if (typeof listener === "object") { | ||
callback = () => listener.handleEvent.apply(listener, arguments); | ||
} | ||
else { | ||
callback = listener; | ||
} | ||
const record = { type, callback, listener, options }; | ||
if (options.once) { | ||
record.callback = function () { | ||
const i = listeners.indexOf(record); | ||
if (i !== -1) { | ||
listeners.splice(i, 1); | ||
} | ||
return callback.apply(this, arguments); | ||
}; | ||
} | ||
if (listeners.some((record1) => record.type === record1.type && | ||
record.listener === record1.listener && | ||
!record.options.capture === !record1.options.capture)) { | ||
return; | ||
} | ||
listeners.push(record); | ||
// TODO: is it possible to separate out the EventTarget delegation logic | ||
for (const value of getChildValues(ctx.ret)) { | ||
if (isEventTarget(value)) { | ||
value.addEventListener(record.type, record.callback, record.options); | ||
} | ||
} | ||
function isListenerOrListenerObject(value) { | ||
return (typeof value === "function" || | ||
(value !== null && | ||
typeof value === "object" && | ||
typeof value.handleEvent === "function")); | ||
} | ||
function removeEventListener(ctx, type, listener, options) { | ||
const listeners = listenersMap.get(ctx); | ||
if (listener == null || listeners == null) { | ||
return; | ||
} | ||
const options1 = normalizeListenerOptions(options); | ||
const i = listeners.findIndex((record) => record.type === type && | ||
record.listener === listener && | ||
!record.options.capture === !options1.capture); | ||
if (i === -1) { | ||
return; | ||
} | ||
const record = listeners[i]; | ||
listeners.splice(i, 1); | ||
// TODO: is it possible to separate out the EventTarget delegation logic | ||
for (const value of getChildValues(ctx.ret)) { | ||
if (isEventTarget(value)) { | ||
value.removeEventListener(record.type, record.callback, record.options); | ||
} | ||
} | ||
} | ||
function dispatchEvent(ctx, ev) { | ||
const path = []; | ||
for (let parent = ctx.parent; parent !== undefined; parent = parent.parent) { | ||
path.push(parent); | ||
} | ||
// We patch the stopImmediatePropagation method because ev.cancelBubble | ||
// only informs us if stopPropagation was called and there are no | ||
// properties which inform us if stopImmediatePropagation was called. | ||
let immediateCancelBubble = false; | ||
const stopImmediatePropagation = ev.stopImmediatePropagation; | ||
setEventProperty(ev, "stopImmediatePropagation", () => { | ||
immediateCancelBubble = true; | ||
return stopImmediatePropagation.call(ev); | ||
}); | ||
setEventProperty(ev, "target", ctx.ctx); | ||
// The only possible errors in this block are errors thrown by callbacks, | ||
// and dispatchEvent will only log these errors rather than throwing | ||
// them. Therefore, we place all code in a try block, log errors in the | ||
// catch block, and use an unsafe return statement in the finally block. | ||
// | ||
// Each early return within the try block returns true because while the | ||
// return value is overridden in the finally block, TypeScript | ||
// (justifiably) does not recognize the unsafe return statement. | ||
// | ||
// TODO: Run all callbacks even if one of them errors | ||
try { | ||
setEventProperty(ev, "eventPhase", CAPTURING_PHASE); | ||
for (let i = path.length - 1; i >= 0; i--) { | ||
const target = path[i]; | ||
const listeners = listenersMap.get(target); | ||
if (listeners) { | ||
setEventProperty(ev, "currentTarget", target.ctx); | ||
for (const record of listeners) { | ||
if (record.type === ev.type && record.options.capture) { | ||
record.callback.call(target.ctx, ev); | ||
if (immediateCancelBubble) { | ||
return true; | ||
} | ||
} | ||
} | ||
} | ||
if (ev.cancelBubble) { | ||
return true; | ||
} | ||
} | ||
{ | ||
const listeners = listenersMap.get(ctx); | ||
if (listeners) { | ||
setEventProperty(ev, "eventPhase", AT_TARGET); | ||
setEventProperty(ev, "currentTarget", ctx.ctx); | ||
for (const record of listeners) { | ||
if (record.type === ev.type) { | ||
record.callback.call(ctx.ctx, ev); | ||
if (immediateCancelBubble) { | ||
return true; | ||
} | ||
} | ||
} | ||
if (ev.cancelBubble) { | ||
return true; | ||
} | ||
} | ||
} | ||
if (ev.bubbles) { | ||
setEventProperty(ev, "eventPhase", BUBBLING_PHASE); | ||
for (let i = 0; i < path.length; i++) { | ||
const target = path[i]; | ||
const listeners = listenersMap.get(target); | ||
if (listeners) { | ||
setEventProperty(ev, "currentTarget", target.ctx); | ||
for (const record of listeners) { | ||
if (record.type === ev.type && !record.options.capture) { | ||
record.callback.call(target.ctx, ev); | ||
if (immediateCancelBubble) { | ||
return true; | ||
} | ||
} | ||
} | ||
} | ||
if (ev.cancelBubble) { | ||
return true; | ||
} | ||
} | ||
} | ||
} | ||
catch (err) { | ||
// TODO: Use setTimeout to rethrow the error. | ||
console.error(err); | ||
} | ||
finally { | ||
setEventProperty(ev, "eventPhase", NONE); | ||
setEventProperty(ev, "currentTarget", null); | ||
// eslint-disable-next-line no-unsafe-finally | ||
return !ev.defaultPrevented; | ||
} | ||
} | ||
function normalizeListenerOptions(options) { | ||
@@ -1531,0 +1531,0 @@ if (typeof options === "boolean") { |
{ | ||
"name": "@bikeshaving/crank", | ||
"version": "0.4.3", | ||
"version": "0.4.4", | ||
"description": "Write JSX-driven components with functions, promises and generators.", | ||
@@ -66,18 +66,18 @@ "homepage": "https://crank.js.org", | ||
"@types/jest": "^26.0.23", | ||
"@typescript-eslint/eslint-plugin": "^4.31.2", | ||
"@typescript-eslint/parser": "^4.31.2", | ||
"eslint": "^7.32.0", | ||
"eslint-config-prettier": "^8.3.0", | ||
"@typescript-eslint/eslint-plugin": "^5.33.0", | ||
"@typescript-eslint/parser": "^5.33.0", | ||
"eslint": "^8.21.0", | ||
"eslint-config-prettier": "^8.5.0", | ||
"eslint-plugin-jest": "^24.4.2", | ||
"eslint-plugin-prettier": "^4.0.0", | ||
"eslint-plugin-react": "^7.26.0", | ||
"eslint-plugin-prettier": "^4.2.1", | ||
"eslint-plugin-react": "^7.30.1", | ||
"jest": "^26.6.3", | ||
"magic-string": "^0.25.7", | ||
"prettier": "^2.4.1", | ||
"rollup": "^2.57.0", | ||
"rollup-plugin-typescript2": "^0.30.0", | ||
"shx": "^0.3.3", | ||
"magic-string": "^0.26.2", | ||
"prettier": "^2.7.1", | ||
"rollup": "^2.77.2", | ||
"rollup-plugin-typescript2": "^0.32.1", | ||
"shx": "^0.3.4", | ||
"ts-jest": "^26.5.6", | ||
"ts-jest-resolver": "^2.0.0", | ||
"typescript": "^4.4.3" | ||
"typescript": "^4.7.4" | ||
}, | ||
@@ -87,2 +87,2 @@ "publishConfig": { | ||
} | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
874680