Browse Source

fix regression in StrictlyEqual (#573)

Marko Lahma 6 years ago
parent
commit
9fbcd80d44

+ 14 - 0
Jint.Tests/Runtime/EngineTests.cs

@@ -1319,6 +1319,20 @@ namespace Jint.Tests.Runtime
             ");
         }
 
+        [Fact]
+        public void ShouldExecuteDromaeoBase64()
+        {
+            RunTest(@"
+var startTest = function () { };
+var test = function (name, fn) { fn(); };
+var endTest = function () { };
+var prep = function (fn) { fn(); };
+            ");
+
+            var content = GetEmbeddedFile("dromaeo-string-base64.js");
+            RunTest(content);
+        }
+
         [Fact]
         public void ShouldExecuteKnockoutWithErrorWhenIntolerant()
         {

+ 147 - 0
Jint.Tests/Runtime/Scripts/dromaeo-string-base64.js

@@ -0,0 +1,147 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla XML-RPC Client component.
+ *
+ * The Initial Developer of the Original Code is
+ * Digital Creations 2, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Martijn Pieters <[email protected]> (original author)
+ *   Samuel Sieb <[email protected]>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// From: http://lxr.mozilla.org/mozilla/source/extensions/xml-rpc/src/nsXmlRpcClient.js#956
+
+/* Convert data (an array of integers) to a Base64 string. */
+var toBase64Table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+var base64Pad = '=';
+
+function toBase64(data) {
+    var result = '';
+    var length = data.length;
+    var i;
+    // Convert every three bytes to 4 ascii characters.
+    for (i = 0; i < (length - 2) ; i += 3) {
+        result += toBase64Table[data.charCodeAt(i) >> 2];
+        result += toBase64Table[((data.charCodeAt(i) & 0x03) << 4) + (data.charCodeAt(i + 1) >> 4)];
+        result += toBase64Table[((data.charCodeAt(i + 1) & 0x0f) << 2) + (data.charCodeAt(i + 2) >> 6)];
+        result += toBase64Table[data.charCodeAt(i + 2) & 0x3f];
+    }
+
+    // Convert the remaining 1 or 2 bytes, pad out to 4 characters.
+    if (length % 3) {
+        i = length - (length % 3);
+        result += toBase64Table[data.charCodeAt(i) >> 2];
+        if ((length % 3) == 2) {
+            result += toBase64Table[((data.charCodeAt(i) & 0x03) << 4) + (data.chartCodeAt(i + 1) >> 4)];
+            result += toBase64Table[(data.charCodeAt(i + 1) & 0x0f) << 2];
+            result += base64Pad;
+        } else {
+            result += toBase64Table[(data.charCodeAt(i) & 0x03) << 4];
+            result += base64Pad + base64Pad;
+        }
+    }
+
+    return result;
+}
+
+/* Convert Base64 data to a string */
+var toBinaryTable = [
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
+    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, 0, -1, -1,
+    -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
+    -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
+];
+
+function base64ToString(data) {
+    var result = '';
+    var leftbits = 0; // number of bits decoded, but yet to be appended
+    var leftdata = 0; // bits decoded, but yet to be appended
+
+    // Convert one by one.
+    for (var i = 0; i < data.length; i++) {
+        var c = toBinaryTable[data.charCodeAt(i) & 0x7f];
+        var padding = (data.charCodeAt(i) == base64Pad.charCodeAt(0));
+        // Skip illegal characters and whitespace
+        if (c == -1) continue;
+
+        // Collect data into leftdata, update bitcount
+        leftdata = (leftdata << 6) | c;
+        leftbits += 6;
+
+        // If we have 8 or more bits, append 8 bits to the result
+        if (leftbits >= 8) {
+            leftbits -= 8;
+            // Append if not padding.
+            if (!padding)
+                result += String.fromCharCode((leftdata >> leftbits) & 0xff);
+            leftdata &= (1 << leftbits) - 1;
+        }
+    }
+
+    // If there are any bits left, the base64 string was corrupted
+    if (leftbits)
+        throw Components.Exception('Corrupted base64 string');
+
+    return result;
+}
+
+startTest("dromaeo-string-base64", '09340c18');
+
+var str = [];
+
+for (var i = 0; i < 4096; i++)
+    str.push(String.fromCharCode((25 * Math.random()) + 97));
+
+str = str.join("");
+str += str;
+str += str;
+
+var base64;
+
+test("Convert String to Base 64", function () {
+    base64 = toBase64(str);
+});
+
+prep(function () {
+    if (!base64)
+        base64 = toBase64(str);
+});
+
+test("Convert Base 64 to String", function () {
+    if (str !== base64ToString(base64)) {
+        throw "String conversion mis-match.";
+    }
+});
+
+endTest();

+ 25 - 28
Jint/Runtime/Interpreter/Expressions/JintBinaryExpression.cs

@@ -56,40 +56,37 @@ namespace Jint.Runtime.Interpreter.Expressions
 
         public static bool StrictlyEqual(JsValue x, JsValue y)
         {
-            if (x._type != y._type)
-            {
-                return false;
-            }
-
-            if (x._type == Types.Boolean || x._type == Types.String)
-            {
-                return x.Equals(y);
-            }
-
-
-            if (x._type >= Types.None && x._type <= Types.Null)
-            {
-                return true;
-            }
+            var typeX = x.Type;
+            var typeY = y.Type;
 
-            if (x is JsNumber jsNumber)
+            if (typeX != typeY)
             {
-                var nx = jsNumber._value;
-                var ny = ((JsNumber) y)._value;
-                return !double.IsNaN(nx) && !double.IsNaN(ny) && nx == ny;
+                return false;
             }
 
-            if (x is IObjectWrapper xw)
+            switch (typeX)
             {
-                if (!(y is IObjectWrapper yw))
-                {
-                    return false;
-                }
-
-                return Equals(xw.Target, yw.Target);
+                case Types.Undefined:
+                case Types.Null:
+                    return true;
+                case Types.Number:
+                    var nx = ((JsNumber) x)._value;
+                    var ny = ((JsNumber) y)._value;
+                    return !double.IsNaN(nx) && !double.IsNaN(ny) && nx == ny;
+                case Types.String:
+                    return x.AsStringWithoutTypeCheck() == y.AsStringWithoutTypeCheck();
+                case Types.Boolean:
+                    return ((JsBoolean) x)._value == ((JsBoolean) y)._value;
+                case Types.Object when x.AsObject() is IObjectWrapper xw:
+                    var yw = y.AsObject() as IObjectWrapper;
+                    if (yw == null)
+                        return false;
+                    return Equals(xw.Target, yw.Target);
+                case Types.None:
+                    return true;
+                default:
+                    return x == y;
             }
-
-            return x == y;
         }
 
         private sealed class JintGenericBinaryExpression : JintBinaryExpression