0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-02-01 20:25:12 -05:00

avoid prototype builtin hasOwnProperty (#2144)

This commit is contained in:
迷渡 2019-04-19 09:56:33 +08:00 committed by Ryan Dahl
parent 2be7e44403
commit d0cd7a39a2
6 changed files with 74 additions and 7 deletions

View file

@ -1,6 +1,6 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
import * as domTypes from "./dom_types";
import { containsOnlyASCII } from "./util";
import { containsOnlyASCII, hasOwnProperty } from "./util";
import { TextEncoder } from "./text_encoding";
export const bytesSymbol = Symbol("bytes");
@ -91,7 +91,7 @@ export class DenoBlob implements domTypes.Blob {
options = options || {};
// Set ending property's default value to "transparent".
if (!options.hasOwnProperty("ending")) {
if (!hasOwnProperty(options, "ending")) {
options.ending = "transparent";
}

View file

@ -32,4 +32,22 @@ test(function blobSlice() {
assertEquals(b4.size, blob.size);
});
test(function blobShouldNotThrowError() {
let hasThrown = false;
try {
const options1: object = {
ending: "utf8",
hasOwnProperty: "hasOwnProperty"
};
const options2: object = Object.create(null);
new Blob(["Hello World"], options1);
new Blob(["Hello World"], options2);
} catch {
hasThrown = true;
}
assertEquals(hasThrown, false);
});
// TODO(qti3e) Test the stored data in a Blob after implementing FileReader API.

View file

@ -2,6 +2,7 @@
// Forked from Node's lib/internal/cli_table.js
import { TextEncoder } from "./text_encoding";
import { hasOwnProperty } from "./util";
const encoder = new TextEncoder();
@ -64,7 +65,7 @@ export function cliTable(head: string[], columns: string[][]): string {
if (rows[j] === undefined) {
rows[j] = [];
}
const value = (rows[j][i] = column.hasOwnProperty(j) ? column[j] : "");
const value = (rows[j][i] = hasOwnProperty(column, j) ? column[j] : "");
const width = columnWidths[i] || 0;
const counted = countBytes(value);
columnWidths[i] = Math.max(width, counted);

View file

@ -1,6 +1,6 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
import * as domTypes from "./dom_types";
import { requiredArguments } from "./util";
import { requiredArguments, hasOwnProperty } from "./util";
/* TODO: This is an incomplete implementation to provide functionality
* for Event. A proper spec is still required for a proper Web API.
@ -16,7 +16,7 @@ export class EventTarget implements domTypes.EventTarget {
_options?: boolean | domTypes.AddEventListenerOptions
): void {
requiredArguments("EventTarget.addEventListener", arguments.length, 2);
if (!this.listeners.hasOwnProperty(type)) {
if (!hasOwnProperty(this.listeners, type)) {
this.listeners[type] = [];
}
if (listener !== null) {
@ -30,7 +30,7 @@ export class EventTarget implements domTypes.EventTarget {
_options?: domTypes.EventListenerOptions | boolean
): void {
requiredArguments("EventTarget.removeEventListener", arguments.length, 2);
if (this.listeners.hasOwnProperty(type) && callback !== null) {
if (hasOwnProperty(this.listeners, type) && callback !== null) {
this.listeners[type] = this.listeners[type].filter(
listener => listener !== callback
);
@ -39,7 +39,7 @@ export class EventTarget implements domTypes.EventTarget {
public dispatchEvent(event: domTypes.Event): boolean {
requiredArguments("EventTarget.dispatchEvent", arguments.length, 1);
if (!this.listeners.hasOwnProperty(event.type)) {
if (!hasOwnProperty(this.listeners, event.type)) {
return true;
}
const stack = this.listeners[event.type].slice();

View file

@ -92,3 +92,21 @@ test(function toStringShouldBeWebCompatibility() {
const target = new EventTarget();
assertEquals(target.toString(), "[object EventTarget]");
});
test(function dispatchEventShouldNotThrowError() {
let hasThrown = false;
try {
const target = new EventTarget();
const event = new Event("hasOwnProperty", {
bubbles: true,
cancelable: false
});
target.addEventListener("hasOwnProperty", () => {});
target.dispatchEvent(event);
} catch {
hasThrown = true;
}
assertEquals(hasThrown, false);
});

View file

@ -142,3 +142,33 @@ export function getPrivateValue<
}
throw new TypeError("Illegal invocation");
}
/**
* Determines whether an object has a property with the specified name.
* Avoid calling prototype builtin `hasOwnProperty` for two reasons:
*
* 1. `hasOwnProperty` is defined on the object as something else:
*
* const options = {
* ending: 'utf8',
* hasOwnProperty: 'foo'
* };
* options.hasOwnProperty('ending') // throws a TypeError
*
* 2. The object doesn't inherit from `Object.prototype`:
*
* const options = Object.create(null);
* options.ending = 'utf8';
* options.hasOwnProperty('ending'); // throws a TypeError
*
* @param obj A Object.
* @param v A property name.
* @see https://eslint.org/docs/rules/no-prototype-builtins
* @internal
*/
export function hasOwnProperty<T>(obj: T, v: PropertyKey): boolean {
if (obj == null) {
return false;
}
return Object.prototype.hasOwnProperty.call(obj, v);
}