diff --git a/.github/workflows/node-aught.yml b/.github/workflows/node-aught.yml index f3cddd8..d6fed62 100644 --- a/.github/workflows/node-aught.yml +++ b/.github/workflows/node-aught.yml @@ -9,10 +9,11 @@ jobs: range: '< 10' type: minors command: npm run tests-only + skip-ls-check: true node: name: 'node < 10' needs: [tests] runs-on: ubuntu-latest steps: - - run: 'echo tests completed' + - run: true diff --git a/.github/workflows/node-tens.yml b/.github/workflows/node-tens.yml index b49ceb1..70f55da 100644 --- a/.github/workflows/node-tens.yml +++ b/.github/workflows/node-tens.yml @@ -15,4 +15,4 @@ jobs: needs: [tests] runs-on: ubuntu-latest steps: - - run: 'echo tests completed' + - run: true diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..993527c --- /dev/null +++ b/index.d.ts @@ -0,0 +1,3 @@ +declare function isArrayBuffer(value: unknown): value is ArrayBuffer; + +export = isArrayBuffer; \ No newline at end of file diff --git a/index.js b/index.js index 2d7110f..126f59e 100644 --- a/index.js +++ b/index.js @@ -4,14 +4,16 @@ var callBind = require('call-bind'); var callBound = require('call-bind/callBound'); var GetIntrinsic = require('get-intrinsic'); -var $ArrayBuffer = GetIntrinsic('ArrayBuffer', true); +var $ArrayBuffer = GetIntrinsic('%ArrayBuffer%', true); +/** @type {undefined | ((receiver: ArrayBuffer) => number) | ((receiver: unknown) => never)} */ var $byteLength = callBound('ArrayBuffer.prototype.byteLength', true); var $toString = callBound('Object.prototype.toString'); // in node 0.10, ArrayBuffers have no prototype methods, but have an own slot-checking `slice` method -var abSlice = $ArrayBuffer && !$byteLength && new $ArrayBuffer().slice; -var $abSlice = abSlice && callBind(abSlice); +var abSlice = !!$ArrayBuffer && !$byteLength && new $ArrayBuffer(0).slice; +var $abSlice = !!abSlice && callBind(abSlice); +/** @type {import('.')} */ module.exports = $byteLength || $abSlice ? function isArrayBuffer(obj) { if (!obj || typeof obj !== 'object') { @@ -19,8 +21,10 @@ module.exports = $byteLength || $abSlice } try { if ($byteLength) { + // @ts-expect-error no idea why TS can't handle the overload $byteLength(obj); } else { + // @ts-expect-error TS chooses not to type-narrow inside a closure $abSlice(obj, 0); } return true; @@ -30,7 +34,7 @@ module.exports = $byteLength || $abSlice } : $ArrayBuffer // in node 0.8, ArrayBuffers have no prototype or own methods, but also no Symbol.toStringTag - ? function IsArrayBuffer(obj) { + ? function isArrayBuffer(obj) { return $toString(obj) === '[object ArrayBuffer]'; } : function isArrayBuffer(obj) { // eslint-disable-line no-unused-vars diff --git a/package.json b/package.json index e68894c..4bc1fef 100644 --- a/package.json +++ b/package.json @@ -7,12 +7,14 @@ ".": "./index.js", "./package.json": "./package.json" }, + "types": "./index.d.ts", "sideEffects": false, "scripts": { "prepack": "npmignore --auto --commentLines=autogenerated", "prepublishOnly": "safe-publish-latest", "prepublish": "not-in-publish || npm run prepublishOnly", "lint": "eslint --ext=.js,.mjs .", + "postlint": "tsc -p .", "pretest": "npm run lint", "tests-only": "nyc tape 'test/**/*.js'", "test": "npm run tests-only --", @@ -43,6 +45,12 @@ "homepage": "https://github.com/inspect-js/is-array-buffer#readme", "devDependencies": { "@ljharb/eslint-config": "^21.1.0", + "@types/call-bind": "^1.0.5", + "@types/es-value-fixtures": "^1.4.4", + "@types/for-each": "^0.3.3", + "@types/get-intrinsic": "^1.2.2", + "@types/object-inspect": "^1.8.4", + "@types/tape": "^5.6.4", "aud": "^2.0.4", "auto-changelog": "^2.4.0", "available-typed-arrays": "^1.0.6", @@ -54,7 +62,8 @@ "nyc": "^10.3.2", "object-inspect": "^1.13.1", "safe-publish-latest": "^2.0.0", - "tape": "^5.7.4" + "tape": "^5.7.4", + "typescript": "^5.4.0-dev.20240202" }, "auto-changelog": { "output": "CHANGELOG.md", diff --git a/test/index.js b/test/index.js index 40c857f..6c452d6 100644 --- a/test/index.js +++ b/test/index.js @@ -11,15 +11,19 @@ var isArrayBuffer = require('..'); test('isArrayBuffer', function (t) { t.equal(typeof isArrayBuffer, 'function', 'is a function'); - var nonABs = v.primitives.concat( + /** @type {unknown[]} */ + var nonABs = [].concat( + // @ts-expect-error TS sucks with [].concat + v.primitives, v.objects, - typeof SharedArrayBuffer === 'function' ? new SharedArrayBuffer() : [] + typeof SharedArrayBuffer === 'function' ? new SharedArrayBuffer(0) : [] ); forEach(nonABs, function (nonAB) { t.equal(isArrayBuffer(nonAB), false, inspect(nonAB) + ' is not an ArrayBuffer'); }); t.test('actual ArrayBuffer instances', { skip: typeof ArrayBuffer === 'undefined' }, function (st) { + // @ts-expect-error TS grumbles about 0 args var ab = new ArrayBuffer(); st.equal(isArrayBuffer(ab), true, inspect(ab) + ' is an ArrayBuffer'); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..2002ce5 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,49 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + + /* Language and Environment */ + "target": "ESNext", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + "typeRoots": ["types"], /* Specify multiple folders that act like './node_modules/@types'. */ + "resolveJsonModule": true, /* Enable importing .json files. */ + // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ + + /* JavaScript Support */ + "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + "maxNodeModuleJsDepth": 0, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + "declarationMap": true, /* Create sourcemaps for d.ts files. */ + "noEmit": true, /* Disable emitting files from a compilation. */ + + /* Interop Constraints */ + "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + + /* Completeness */ + //"skipLibCheck": true /* Skip type checking all .d.ts files. */ + }, + "exclude": [ + "coverage" + ] +}