1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-22 15:24:46 -05:00

runtime arg check URLSearchParams (#1390)

This commit is contained in:
迷渡 2018-12-24 12:07:58 +08:00 committed by Ryan Dahl
parent 9909e8a759
commit 7d0e1050d3
3 changed files with 73 additions and 3 deletions

View file

@ -1,3 +1,5 @@
import { requiredArguments } from "./util";
// Copyright 2018 the Deno authors. All rights reserved. MIT license. // Copyright 2018 the Deno authors. All rights reserved. MIT license.
export class URLSearchParams { export class URLSearchParams {
private params: Array<[string, string]> = []; private params: Array<[string, string]> = [];
@ -46,7 +48,8 @@ export class URLSearchParams {
* searchParams.append('name', 'second'); * searchParams.append('name', 'second');
*/ */
append(name: string, value: string): void { append(name: string, value: string): void {
this.params.push([name, value]); requiredArguments("URLSearchParams.append", arguments.length, 2);
this.params.push([String(name), value]);
} }
/** Deletes the given search parameter and its associated value, /** Deletes the given search parameter and its associated value,
@ -55,6 +58,8 @@ export class URLSearchParams {
* searchParams.delete('name'); * searchParams.delete('name');
*/ */
delete(name: string): void { delete(name: string): void {
requiredArguments("URLSearchParams.delete", arguments.length, 1);
name = String(name);
let i = 0; let i = 0;
while (i < this.params.length) { while (i < this.params.length) {
if (this.params[i][0] === name) { if (this.params[i][0] === name) {
@ -71,6 +76,8 @@ export class URLSearchParams {
* searchParams.getAll('name'); * searchParams.getAll('name');
*/ */
getAll(name: string): string[] { getAll(name: string): string[] {
requiredArguments("URLSearchParams.getAll", arguments.length, 1);
name = String(name);
const values = []; const values = [];
for (const entry of this.params) { for (const entry of this.params) {
if (entry[0] === name) { if (entry[0] === name) {
@ -86,6 +93,8 @@ export class URLSearchParams {
* searchParams.get('name'); * searchParams.get('name');
*/ */
get(name: string): string | null { get(name: string): string | null {
requiredArguments("URLSearchParams.get", arguments.length, 1);
name = String(name);
for (const entry of this.params) { for (const entry of this.params) {
if (entry[0] === name) { if (entry[0] === name) {
return entry[1]; return entry[1];
@ -101,6 +110,8 @@ export class URLSearchParams {
* searchParams.has('name'); * searchParams.has('name');
*/ */
has(name: string): boolean { has(name: string): boolean {
requiredArguments("URLSearchParams.has", arguments.length, 1);
name = String(name);
return this.params.some(entry => entry[0] === name); return this.params.some(entry => entry[0] === name);
} }
@ -112,9 +123,12 @@ export class URLSearchParams {
* searchParams.set('name', 'value'); * searchParams.set('name', 'value');
*/ */
set(name: string, value: string): void { set(name: string, value: string): void {
requiredArguments("URLSearchParams.set", arguments.length, 2);
// If there are any name-value pairs whose name is name, in list, // If there are any name-value pairs whose name is name, in list,
// set the value of the first such name-value pair to value // set the value of the first such name-value pair to value
// and remove the others. // and remove the others.
name = String(name);
let found = false; let found = false;
let i = 0; let i = 0;
while (i < this.params.length) { while (i < this.params.length) {
@ -122,13 +136,14 @@ export class URLSearchParams {
if (!found) { if (!found) {
this.params[i][1] = value; this.params[i][1] = value;
found = true; found = true;
i++;
} else { } else {
this.params.splice(i, 1); this.params.splice(i, 1);
continue;
}
} }
} else {
i++; i++;
} }
}
// Otherwise, append a new name-value pair whose name is name // Otherwise, append a new name-value pair whose name is name
// and value is value, to list. // and value is value, to list.
@ -163,9 +178,12 @@ export class URLSearchParams {
// tslint:disable-next-line:no-any // tslint:disable-next-line:no-any
thisArg?: any thisArg?: any
) { ) {
requiredArguments("URLSearchParams.forEach", arguments.length, 1);
if (typeof thisArg !== "undefined") { if (typeof thisArg !== "undefined") {
callbackfn = callbackfn.bind(thisArg); callbackfn = callbackfn.bind(thisArg);
} }
for (const [key, value] of this.entries()) { for (const [key, value] of this.entries()) {
callbackfn(value, key, this); callbackfn(value, key, this);
} }

View file

@ -138,3 +138,41 @@ test(function urlSearchParamsShouldThrowTypeError() {
assertEqual(hasThrown, 2); assertEqual(hasThrown, 2);
}); });
test(function urlSearchParamsAppendArgumentsCheck() {
const methodRequireOneParam = ["delete", "getAll", "get", "has", "forEach"];
const methodRequireTwoParams = ["append", "set"];
methodRequireOneParam.concat(methodRequireTwoParams).forEach(method => {
const searchParams = new URLSearchParams();
let hasThrown = 0;
try {
searchParams[method]();
hasThrown = 1;
} catch (err) {
if (err instanceof TypeError) {
hasThrown = 2;
} else {
hasThrown = 3;
}
}
assertEqual(hasThrown, 2);
});
methodRequireTwoParams.forEach(method => {
const searchParams = new URLSearchParams();
let hasThrown = 0;
try {
searchParams[method]("foo");
hasThrown = 1;
} catch (err) {
if (err instanceof TypeError) {
hasThrown = 2;
} else {
hasThrown = 3;
}
}
assertEqual(hasThrown, 2);
});
});

View file

@ -137,3 +137,17 @@ export function isTypedArray(x: unknown): x is TypedArray {
export function isObject(o: unknown): o is object { export function isObject(o: unknown): o is object {
return o != null && typeof o === "object"; return o != null && typeof o === "object";
} }
// @internal
export function requiredArguments(
name: string,
length: number,
required: number
): void {
if (length < required) {
const errMsg = `${name} requires at least ${required} argument${
required === 1 ? "" : "s"
}, but only ${length} present`;
throw new TypeError(errMsg);
}
}