Skip to content

Commit

Permalink
Fix conflicts with master
Browse files Browse the repository at this point in the history
  • Loading branch information
trueadm committed Sep 4, 2019
2 parents b3b3df6 + af03276 commit 28b73a6
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export default function ProfilingImportExportButtons() {
const {profilerStore} = store;

const inputRef = useRef<HTMLInputElement | null>(null);
const downloadRef = useRef<HTMLAnchorElement | null>(null);

const {dispatch: modalDialogDispatch} = useContext(ModalDialogContext);

Expand All @@ -38,7 +39,7 @@ export default function ProfilingImportExportButtons() {
return;
}

if (profilingData !== null) {
if (profilingData !== null && downloadRef.current !== null) {
const profilingDataExport = prepareProfilingDataExport(profilingData);
const date = new Date();
const dateString = date
Expand All @@ -54,6 +55,7 @@ export default function ProfilingImportExportButtons() {
})
.replace(/:/g, '-');
downloadFile(
downloadRef.current,
`profiling-data.${dateString}.${timeString}.json`,
JSON.stringify(profilingDataExport, null, 2),
);
Expand Down Expand Up @@ -114,6 +116,7 @@ export default function ProfilingImportExportButtons() {
onChange={handleFiles}
tabIndex={-1}
/>
<a ref={downloadRef} className={styles.Input} />
<Button
disabled={isProfiling}
onClick={uploadData}
Expand Down
11 changes: 5 additions & 6 deletions packages/react-devtools-shared/src/devtools/views/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,11 @@ export function serializeHooksForCopy(hooks: HooksTree | null): string {
// Without this, we would see a "Download failed: network error" failure.
let downloadUrl = null;

export function downloadFile(filename: string, text: string): void {
export function downloadFile(
element: HTMLAnchorElement,
filename: string,
text: string,
): void {
const blob = new Blob([text], {type: 'text/plain;charset=utf-8'});

if (downloadUrl !== null) {
Expand All @@ -187,15 +191,10 @@ export function downloadFile(filename: string, text: string): void {

downloadUrl = URL.createObjectURL(blob);

const element = document.createElement('a');
element.setAttribute('href', downloadUrl);
element.setAttribute('download', filename);
element.style.display = 'none';
((document.body: any): HTMLBodyElement).appendChild(element);

element.click();

((document.body: any): HTMLBodyElement).removeChild(element);
}

export function truncateText(text: string, maxLength: number): string {
Expand Down
2 changes: 2 additions & 0 deletions packages/react-devtools/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
</summary>

<!-- Upcoming changes go here -->
#### Bug fixes
* Profiler correctly saves/exports profiling data in Firefox now. ([hristo-kanchev](https://github.com/hristo-kanchev) in [#16612](https://github.com/facebook/react/pull/16612))
</details>

## 4.0.6 (August 26, 2019)
Expand Down
62 changes: 57 additions & 5 deletions packages/react-events/src/dom/Keyboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type KeyboardProps = {
disabled: boolean,
onKeyDown: (e: KeyboardEvent) => void,
onKeyUp: (e: KeyboardEvent) => void,
preventKeys: Array<string>,
};

type KeyboardEvent = {|
Expand All @@ -36,9 +37,12 @@ type KeyboardEvent = {|
target: Element | Document,
type: KeyboardEventType,
timeStamp: number,
defaultPrevented: boolean,
|};

const targetEventTypes = ['keydown', 'keyup'];
const isArray = Array.isArray;
const targetEventTypes = ['keydown_active', 'keyup'];
const modifiers = ['altKey', 'ctrlKey', 'metaKey', 'shiftKey'];

/**
* Normalization of deprecated HTML5 `key` values
Expand Down Expand Up @@ -107,7 +111,7 @@ function isFunction(obj): boolean {
return typeof obj === 'function';
}

function getEventKey(nativeEvent): string {
function getEventKey(nativeEvent: Object): string {
const nativeKey = nativeEvent.key;
if (nativeKey) {
// Normalize inconsistent values reported by browsers due to
Expand All @@ -127,6 +131,7 @@ function createKeyboardEvent(
event: ReactDOMResponderEvent,
context: ReactDOMResponderContext,
type: KeyboardEventType,
defaultPrevented: boolean,
): KeyboardEvent {
const nativeEvent = (event: any).nativeEvent;
const {
Expand All @@ -143,6 +148,7 @@ function createKeyboardEvent(
return {
altKey,
ctrlKey,
defaultPrevented,
isComposing,
key: getEventKey(nativeEvent),
location,
Expand All @@ -160,8 +166,14 @@ function dispatchKeyboardEvent(
listener: KeyboardEvent => void,
context: ReactDOMResponderContext,
type: KeyboardEventType,
defaultPrevented: boolean,
): void {
const syntheticEvent = createKeyboardEvent(event, context, type);
const syntheticEvent = createKeyboardEvent(
event,
context,
type,
defaultPrevented,
);
context.dispatchEvent(syntheticEvent, listener, DiscreteEvent);
}

Expand All @@ -173,19 +185,59 @@ const keyboardResponderImpl = {
props: KeyboardProps,
): void {
const {type} = event;
const nativeEvent: any = event.nativeEvent;

if (props.disabled) {
return;
}
let defaultPrevented = nativeEvent.defaultPrevented === true;
if (type === 'keydown') {
const preventKeys = props.preventKeys;
if (!defaultPrevented && isArray(preventKeys)) {
preventKeyLoop: for (let i = 0; i < preventKeys.length; i++) {
const preventKey = preventKeys[i];
let key = preventKey;

if (isArray(preventKey)) {
key = preventKey[0];
const config = ((preventKey[1]: any): Object);
for (let s = 0; s < modifiers.length; s++) {
const modifier = modifiers[s];
if (
(config[modifier] && !nativeEvent[modifier]) ||
(!config[modifier] && nativeEvent[modifier])
) {
continue preventKeyLoop;
}
}
}
if (key === getEventKey(nativeEvent)) {
defaultPrevented = true;
nativeEvent.preventDefault();
break;
}
}
}
const onKeyDown = props.onKeyDown;
if (isFunction(onKeyDown)) {
dispatchKeyboardEvent(event, onKeyDown, context, 'keydown');
dispatchKeyboardEvent(
event,
onKeyDown,
context,
'keydown',
defaultPrevented,
);
}
} else if (type === 'keyup') {
const onKeyUp = props.onKeyUp;
if (isFunction(onKeyUp)) {
dispatchKeyboardEvent(event, onKeyUp, context, 'keyup');
dispatchKeyboardEvent(
event,
onKeyUp,
context,
'keyup',
defaultPrevented,
);
}
}
},
Expand Down
128 changes: 128 additions & 0 deletions packages/react-events/src/dom/__tests__/Keyboard-test.internal.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,134 @@ describe('Keyboard event responder', () => {
});
});

describe('preventKeys', () => {
it('onKeyDown is default prevented', () => {
const onKeyDown = jest.fn();
const ref = React.createRef();
const Component = () => {
const listener = useKeyboard({
onKeyDown,
preventKeys: ['Tab'],
});
return <div ref={ref} listeners={listener} />;
};
ReactDOM.render(<Component />, container);

const preventDefault = jest.fn();
const target = createEventTarget(ref.current);
target.keydown({key: 'Tab', preventDefault});
expect(onKeyDown).toHaveBeenCalledTimes(1);
expect(preventDefault).toBeCalled();
expect(onKeyDown).toHaveBeenCalledWith(
expect.objectContaining({
key: 'Tab',
type: 'keydown',
defaultPrevented: true,
}),
);
});

it('onKeyDown is default prevented (falsy modifier keys)', () => {
let onKeyDown = jest.fn();
let ref = React.createRef();
let Component = () => {
const listener = useKeyboard({
onKeyDown,
preventKeys: [['Tab', {metaKey: false}]],
});
return <div ref={ref} listeners={listener} />;
};
ReactDOM.render(<Component />, container);

let preventDefault = jest.fn();
let target = createEventTarget(ref.current);
target.keydown({key: 'Tab', preventDefault, metaKey: true});
expect(onKeyDown).toHaveBeenCalledTimes(1);
expect(preventDefault).not.toBeCalled();
expect(onKeyDown).toHaveBeenCalledWith(
expect.objectContaining({
key: 'Tab',
type: 'keydown',
defaultPrevented: false,
}),
);

onKeyDown = jest.fn();
ref = React.createRef();
Component = () => {
const listener = useKeyboard({
onKeyDown,
preventKeys: [['Tab', {metaKey: true}]],
});
return <div ref={ref} listeners={listener} />;
};
ReactDOM.render(<Component />, container);

preventDefault = jest.fn();
target = createEventTarget(ref.current);
target.keydown({key: 'Tab', preventDefault, metaKey: false});
expect(onKeyDown).toHaveBeenCalledTimes(1);
expect(preventDefault).not.toBeCalled();
expect(onKeyDown).toHaveBeenCalledWith(
expect.objectContaining({
key: 'Tab',
type: 'keydown',
defaultPrevented: false,
}),
);
});

it('onKeyDown is default prevented (truthy modifier keys)', () => {
let onKeyDown = jest.fn();
let ref = React.createRef();
let Component = () => {
const listener = useKeyboard({
onKeyDown,
preventKeys: [['Tab', {metaKey: true}]],
});
return <div ref={ref} listeners={listener} />;
};
ReactDOM.render(<Component />, container);

let preventDefault = jest.fn();
let target = createEventTarget(ref.current);
target.keydown({key: 'Tab', preventDefault, metaKey: true});
expect(onKeyDown).toHaveBeenCalledTimes(1);
expect(preventDefault).toBeCalled();
expect(onKeyDown).toHaveBeenCalledWith(
expect.objectContaining({
key: 'Tab',
type: 'keydown',
defaultPrevented: true,
}),
);

onKeyDown = jest.fn();
ref = React.createRef();
Component = () => {
const listener = useKeyboard({
onKeyDown,
preventKeys: [['Tab', {metaKey: false}]],
});
return <div ref={ref} listeners={listener} />;
};
ReactDOM.render(<Component />, container);

preventDefault = jest.fn();
target = createEventTarget(ref.current);
target.keydown({key: 'Tab', preventDefault, metaKey: false});
expect(onKeyDown).toHaveBeenCalledTimes(1);
expect(preventDefault).toBeCalled();
expect(onKeyDown).toHaveBeenCalledWith(
expect.objectContaining({
key: 'Tab',
type: 'keydown',
defaultPrevented: true,
}),
);
});
});

describe('onKeyUp', () => {
let onKeyDown, onKeyUp, ref;

Expand Down

0 comments on commit 28b73a6

Please sign in to comment.