Skip to content

Commit 815f646

Browse files
add prototype
1 parent 7f23d79 commit 815f646

File tree

6 files changed

+328
-0
lines changed

6 files changed

+328
-0
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/tsconfig.tsbuildinfo
2+
/node_modules
3+
/lib

package-lock.json

+28
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"private": true,
3+
"name": "proposal-iterator-chunking",
4+
"version": "1.0.0",
5+
"description": "",
6+
"main": "lib/index.js",
7+
"scripts": {
8+
"build": "tsc",
9+
"test": "node --test test"
10+
},
11+
"repository": {
12+
"type": "git",
13+
"url": "git+ssh://[email protected]/tc39/proposal-iterator-chunking.git"
14+
},
15+
"author": "Michael Ficarra",
16+
"bugs": {
17+
"url": "https://github.com/tc39/proposal-iterator-chunking/issues"
18+
},
19+
"homepage": "https://github.com/tc39/proposal-iterator-chunking#readme",
20+
"devDependencies": {
21+
"typescript": "5.2.2"
22+
}
23+
}

src/index.ts

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
const IteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([].values()))
2+
3+
function liftIterator<A>(iter: Iterator<A>): Iterable<A> {
4+
return { [Symbol.iterator]() { return iter; } };
5+
}
6+
7+
function* chunksImpl<A>(iter: Iterator<A>, chunkSize: number): Generator<Array<A>> {
8+
let buffer = [];
9+
for (const elem of liftIterator(iter)) {
10+
buffer.push(elem);
11+
if (buffer.length === chunkSize) {
12+
yield buffer;
13+
buffer = [];
14+
}
15+
}
16+
if (buffer.length > 0) {
17+
yield buffer;
18+
}
19+
}
20+
21+
function chunks<A>(this: Iterator<A>, chunkSize: number): Generator<Array<A>>
22+
function chunks(this: unknown, chunkSize: unknown = 2): Generator<unknown> {
23+
if (
24+
typeof chunkSize !== 'number'
25+
|| chunkSize <= 0
26+
|| Math.floor(chunkSize) !== chunkSize
27+
|| chunkSize >= Math.pow(2, 53)
28+
) {
29+
throw new RangeError;
30+
}
31+
return chunksImpl(this as Iterator<unknown>, chunkSize)
32+
}
33+
34+
function* windowsImpl<A>(iter: Iterator<A>, windowSize: number): Generator<Array<A>> {
35+
let buffer = [];
36+
for (const elem of liftIterator(iter)) {
37+
if (buffer.length === windowSize) {
38+
buffer.shift();
39+
}
40+
buffer.push(elem);
41+
if (buffer.length === windowSize) {
42+
yield buffer.slice();
43+
}
44+
}
45+
}
46+
47+
function windows<A>(this: Iterator<A>, windowSize: number): Generator<Array<A>>
48+
function windows(this: unknown, windowSize: unknown = 2): Generator<unknown> {
49+
if (
50+
typeof windowSize !== 'number'
51+
|| windowSize <= 0
52+
|| Math.floor(windowSize) !== windowSize
53+
|| windowSize >= Math.pow(2, 53)
54+
) {
55+
throw new RangeError;
56+
}
57+
return windowsImpl(this as Iterator<unknown>, windowSize)
58+
}
59+
60+
Object.defineProperty(IteratorPrototype, 'chunks', {
61+
configurable: true,
62+
writable: true,
63+
enumerable: false,
64+
value: chunks,
65+
});
66+
67+
Object.defineProperty(IteratorPrototype, 'windows', {
68+
configurable: true,
69+
writable: true,
70+
enumerable: false,
71+
value: windows,
72+
});

test/index.mjs

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import { test } from 'node:test';
2+
import * as assert from 'node:assert/strict';
3+
import '../lib/index.js';
4+
5+
function* nats(limit) {
6+
let n = 0;
7+
while (n < limit) {
8+
yield n;
9+
++n;
10+
}
11+
}
12+
13+
test('chunks', async t => {
14+
assert.deepEqual(
15+
Array.from(nats(5).chunks()),
16+
[[0, 1], [2, 3], [4]],
17+
);
18+
assert.deepEqual(
19+
Array.from(nats(5).chunks(1)),
20+
[[0], [1], [2], [3], [4]],
21+
);
22+
assert.deepEqual(
23+
Array.from(nats(6).chunks(2)),
24+
[[0, 1], [2, 3], [4, 5]],
25+
);
26+
assert.deepEqual(
27+
Array.from(nats(6).chunks(3)),
28+
[[0, 1, 2], [3, 4, 5]],
29+
);
30+
assert.deepEqual(
31+
Array.from(nats(6).chunks(100)),
32+
[[0, 1, 2, 3, 4, 5]],
33+
);
34+
assert.deepEqual(
35+
Array.from(nats(0).chunks(2)),
36+
[],
37+
);
38+
39+
assert.throws(() => {
40+
nats(1).chunks([2]);
41+
}, RangeError)
42+
assert.throws(() => {
43+
nats(1).chunks(0);
44+
}, RangeError)
45+
assert.throws(() => {
46+
nats(1).chunks(-1);
47+
}, RangeError)
48+
assert.throws(() => {
49+
nats(1).chunks(1.5);
50+
}, RangeError)
51+
assert.throws(() => {
52+
nats(1).chunks(Math.pow(2, 53));
53+
}, RangeError)
54+
});
55+
56+
test('windows', async t => {
57+
assert.deepEqual(
58+
Array.from(nats(5).windows()),
59+
[[0, 1], [1, 2], [2, 3], [3, 4]],
60+
);
61+
assert.deepEqual(
62+
Array.from(nats(5).windows(1)),
63+
[[0], [1], [2], [3], [4]],
64+
);
65+
assert.deepEqual(
66+
Array.from(nats(6).windows(3)),
67+
[[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5]],
68+
);
69+
assert.deepEqual(
70+
Array.from(nats(6).windows(100)),
71+
[],
72+
);
73+
assert.deepEqual(
74+
Array.from(nats(0).windows(2)),
75+
[],
76+
);
77+
78+
assert.throws(() => {
79+
nats(1).windows([2]);
80+
}, RangeError)
81+
assert.throws(() => {
82+
nats(1).windows(0);
83+
}, RangeError)
84+
assert.throws(() => {
85+
nats(1).windows(-1);
86+
}, RangeError)
87+
assert.throws(() => {
88+
nats(1).windows(1.5);
89+
}, RangeError)
90+
assert.throws(() => {
91+
nats(1).windows(Math.pow(2, 53));
92+
}, RangeError)
93+
});

tsconfig.json

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
{
2+
"compilerOptions": {
3+
/* Visit https://aka.ms/tsconfig to read more about this file */
4+
5+
/* Projects */
6+
"incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
7+
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
8+
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
9+
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
10+
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
11+
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
12+
13+
/* Language and Environment */
14+
"target": "es2022", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
15+
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
16+
// "jsx": "preserve", /* Specify what JSX code is generated. */
17+
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
18+
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
19+
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
20+
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
21+
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
22+
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
23+
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
24+
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
25+
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
26+
27+
/* Modules */
28+
"module": "es2022", /* Specify what module code is generated. */
29+
"rootDir": "src", /* Specify the root folder within your source files. */
30+
// "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
31+
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
32+
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
33+
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
34+
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
35+
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
36+
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
37+
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
38+
// "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
39+
// "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
40+
// "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
41+
// "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
42+
// "resolveJsonModule": true, /* Enable importing .json files. */
43+
// "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
44+
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
45+
46+
/* JavaScript Support */
47+
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
48+
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
49+
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
50+
51+
/* Emit */
52+
"declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
53+
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
54+
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
55+
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
56+
"inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
57+
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
58+
"outDir": "lib", /* Specify an output folder for all emitted files. */
59+
"removeComments": true, /* Disable emitting comments. */
60+
// "noEmit": true, /* Disable emitting files from a compilation. */
61+
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
62+
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
63+
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
64+
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
65+
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
66+
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
67+
"emitBOM": false, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
68+
"newLine": "lf", /* Set the newline character for emitting files. */
69+
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
70+
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
71+
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
72+
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
73+
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
74+
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
75+
76+
/* Interop Constraints */
77+
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
78+
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
79+
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
80+
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
81+
"preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
82+
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
83+
84+
/* Type Checking */
85+
"strict": true, /* Enable all strict type-checking options. */
86+
"noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
87+
"strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
88+
"strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
89+
"strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
90+
"strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
91+
"noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
92+
"useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
93+
"alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
94+
"noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
95+
"noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
96+
"exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
97+
"noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
98+
"noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
99+
"noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
100+
"noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
101+
"noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
102+
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
103+
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
104+
105+
/* Completeness */
106+
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
107+
"skipLibCheck": true /* Skip type checking all .d.ts files. */
108+
}
109+
}

0 commit comments

Comments
 (0)