Skip to content

Commit

Permalink
Merge pull request skulpt#508 from JohnDenker/master
Browse files Browse the repository at this point in the history
unichr now working
  • Loading branch information
Albert-Jan Nijburg committed Sep 30, 2015
2 parents 2f9ffaf + bc97184 commit df2c31a
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 3 deletions.
1 change: 1 addition & 0 deletions skulpt.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ def bowerProperty(name):
'src/object.js',
'src/function.js',
'src/builtin.js',
'src/fromcodepoint.js', # should become unnecessary, eventually
'src/errors.js',
'src/native.js',
'src/method.js',
Expand Down
21 changes: 18 additions & 3 deletions src/builtin.js
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,24 @@ Sk.builtin.chr = function chr (x) {
return new Sk.builtin.str(String.fromCharCode(x));
};

Sk.builtin.unichr = function unichr (x) {
Sk.builtin.pyCheckArgs("chr", arguments, 1, 1);
if (!Sk.builtin.checkInt(x)) {
throw new Sk.builtin.TypeError("an integer is required");
}
x = Sk.builtin.asnum$(x);

try {
return new Sk.builtin.str(String.fromCodePoint(x));
}
catch (err) {
if (err instanceof RangeError) {
throw new Sk.builtin.ValueError(err.message);
}
throw err;
}
};

Sk.builtin.int2str_ = function helper_ (x, radix, prefix) {
var suffix;
var str = "";
Expand Down Expand Up @@ -1195,9 +1213,6 @@ Sk.builtin.reload = function reload () {
Sk.builtin.reversed = function reversed () {
throw new Sk.builtin.NotImplementedError("reversed is not yet implemented");
};
Sk.builtin.unichr = function unichr () {
throw new Sk.builtin.NotImplementedError("unichr is not yet implemented");
};
Sk.builtin.vars = function vars () {
throw new Sk.builtin.NotImplementedError("vars is not yet implemented");
};
Expand Down
63 changes: 63 additions & 0 deletions src/fromcodepoint.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*! https://mths.be/fromcodepoint v0.2.1 by @mathias */
if (!String.fromCodePoint) {
(function() {
var defineProperty = (function() {
// IE 8 only supports `Object.defineProperty` on DOM elements
var result;
try {
var object = {};
var $defineProperty = Object.defineProperty;
result = $defineProperty(object, "foo", object) && $defineProperty;
} catch(error) {}
return result;
}());
var stringFromCharCode = String.fromCharCode;
var floor = Math.floor;
var fromCodePoint = function(_) {
var MAX_SIZE = 0x4000;
var codeUnits = [];
var highSurrogate;
var lowSurrogate;
var index = -1;
var length = arguments.length;
if (!length) {
return "";
}
var result = "";
while (++index < length) {
var codePoint = Number(arguments[index]);
if (
!isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity`
codePoint < 0 || // not a valid Unicode code point
codePoint > 0x10FFFF || // not a valid Unicode code point
floor(codePoint) != codePoint // not an integer
) {
throw RangeError("Invalid code point: " + codePoint);
}
if (codePoint <= 0xFFFF) { // BMP code point
codeUnits.push(codePoint);
} else { // Astral code point; split in surrogate halves
// https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
codePoint -= 0x10000;
highSurrogate = (codePoint >> 10) + 0xD800;
lowSurrogate = (codePoint % 0x400) + 0xDC00;
codeUnits.push(highSurrogate, lowSurrogate);
}
if (index + 1 == length || codeUnits.length > MAX_SIZE) {
result += stringFromCharCode.apply(null, codeUnits);
codeUnits.length = 0;
}
}
return result;
};
if (defineProperty) {
defineProperty(String, "fromCodePoint", {
"value": fromCodePoint,
"configurable": true,
"writable": true
});
} else {
String.fromCodePoint = fromCodePoint;
}
}());
}
44 changes: 44 additions & 0 deletions test/unit/test_unichr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
__author__ = 'jsd'

# Test the unichr() function
# This is hardly an exhaustive check,
# but spot-checking is better than no checking.

import unittest

class TestUnichr(unittest.TestCase):
# one-byte code (basic plane):
def testOne(self):
self.assertEqual(unichr(0x61), 'a')
def testOneMore(self):
self.assertEqual(unichr(0x61), u'a')

# two-byte code:
def testTwo(self):
self.assertEqual(unichr(0x3c9), u'ω')
# three-byte code:
def testThree(self):
self.assertEqual(unichr(0x2207), u'∇')

# four-byte code (astral plane)
def testFour(self):
self.assertEqual(unichr(0x1d11e), u'𝄞')

def testFive(self):
ex = 0
try:
s1 = unichr(-1) # should throw ValueError
except ValueError:
ex = 1
self.assertEqual(1, ex)

def testSix(self):
ex = 0
try:
s1 = unichr(1<<22) # should throw ValueError
except ValueError:
ex = 1
self.assertEqual(1, ex)

if __name__ == '__main__':
unittest.main()

0 comments on commit df2c31a

Please sign in to comment.