blob: b887631bc15e5383752527b1880130d4dc1ee2f8 [file] [log] [blame]
Leo Repp58b9f112021-11-22 11:57:47 +01001'use strict';
2
3var GetIntrinsic = require('get-intrinsic');
4
5var $TypeError = GetIntrinsic('%TypeError%');
6var callBound = require('call-bind/callBound');
7var isLeadingSurrogate = require('../helpers/isLeadingSurrogate');
8var isTrailingSurrogate = require('../helpers/isTrailingSurrogate');
9
10var Type = require('./Type');
11var UTF16DecodeSurrogatePair = require('./UTF16DecodeSurrogatePair');
12
13var $charAt = callBound('String.prototype.charAt');
14var $charCodeAt = callBound('String.prototype.charCodeAt');
15
16// https://262.ecma-international.org/11.0/#sec-codepointat
17
18module.exports = function CodePointAt(string, position) {
19 if (Type(string) !== 'String') {
20 throw new $TypeError('Assertion failed: `string` must be a String');
21 }
22 var size = string.length;
23 if (position < 0 || position >= size) {
24 throw new $TypeError('Assertion failed: `position` must be >= 0, and < the length of `string`');
25 }
26 var first = $charCodeAt(string, position);
27 var cp = $charAt(string, position);
28 var firstIsLeading = isLeadingSurrogate(first);
29 var firstIsTrailing = isTrailingSurrogate(first);
30 if (!firstIsLeading && !firstIsTrailing) {
31 return {
32 '[[CodePoint]]': cp,
33 '[[CodeUnitCount]]': 1,
34 '[[IsUnpairedSurrogate]]': false
35 };
36 }
37 if (firstIsTrailing || (position + 1 === size)) {
38 return {
39 '[[CodePoint]]': cp,
40 '[[CodeUnitCount]]': 1,
41 '[[IsUnpairedSurrogate]]': true
42 };
43 }
44 var second = $charCodeAt(string, position + 1);
45 if (!isTrailingSurrogate(second)) {
46 return {
47 '[[CodePoint]]': cp,
48 '[[CodeUnitCount]]': 1,
49 '[[IsUnpairedSurrogate]]': true
50 };
51 }
52
53 return {
54 '[[CodePoint]]': UTF16DecodeSurrogatePair(first, second),
55 '[[CodeUnitCount]]': 2,
56 '[[IsUnpairedSurrogate]]': false
57 };
58};