// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// @dart = 2.7

import "native_testing.dart";
import 'dart:_foreign_helper' show JS_INTERCEPTOR_CONSTANT;
import 'dart:_interceptors'
    show
        Interceptor,
        JavaScriptObject,
        PlainJavaScriptObject,
        UnknownJavaScriptObject;

// Test for safe formatting of JavaScript objects by Error.safeToString.

@Native('PPPP')
class Purple {}

@Native('QQQQ')
class Q {}

@Native('RRRR')
class Rascal {
  toString() => 'RRRRRRRR';
}

makeA() native;
makeB() native;
makeC() native;
makeD() native;
makeE() native;
makeP() native;
makeQ() native;
makeR() native;

void setup() {
  JS('', r"""
(function(){
  self.makeA = function(){return {hello: 123};};

  function BB(){}
  self.makeB = function(){return new BB();};

  function CC(){}
  self.makeC = function(){
    var x = new CC();
    x.constructor = null;  // Foils constructor lookup.
    return x;
  };

  function DD(){}
  self.makeD = function(){
    var x = new DD();
    x.constructor = {name: 'DDxxx'};  // Foils constructor lookup.
    return x;
  };

  function EE(){}
  self.makeE = function(){
    var x = new EE();
    x.constructor = function Liar(){};  // Looks like a legitimate constructor.
    return x;
  };

  function PPPP(){}
  self.makeP = function(){return new PPPP();};

  function QQQQ(){}
  self.makeQ = function(){return new QQQQ();};

  function RRRR(){}
  self.makeR = function(){return new RRRR();};

  self.nativeConstructor(PPPP);
  self.nativeConstructor(QQQQ);
  self.nativeConstructor(RRRR);
})()""");
  applyTestExtensions(['PPPP', 'QQQQ', 'RRRR']);
}

expectTypeName(expectedName, s) {
  var m = new RegExp(r"Instance of '(.*)'").firstMatch(s);
  Expect.isNotNull(m);
  var name = m.group(1);
  Expect.isTrue(
      expectedName == name || name.length <= 3 || name.startsWith('minified:'),
      "Is '$expectedName' or minified: '$name'");
}

final plainJsString =
    Error.safeToString(JS_INTERCEPTOR_CONSTANT(PlainJavaScriptObject));

final unknownJsString =
    Error.safeToString(JS_INTERCEPTOR_CONSTANT(UnknownJavaScriptObject));

final interceptorString =
    Error.safeToString(JS_INTERCEPTOR_CONSTANT(Interceptor));

testDistinctInterceptors() {
  // Test invariants needed for the other tests.

  Expect.notEquals(plainJsString, unknownJsString);
  Expect.notEquals(plainJsString, interceptorString);
  Expect.notEquals(unknownJsString, interceptorString);

  expectTypeName('PlainJavaScriptObject', plainJsString);
  expectTypeName('UnknownJavaScriptObject', unknownJsString);
  expectTypeName('Interceptor', interceptorString);

  // Sometimes interceptor *objects* are used instead of the prototypes. Check
  // these work too.
  var plain2 = Error.safeToString(const PlainJavaScriptObject());
  Expect.equals(plainJsString, plain2);

  var unk2 = Error.safeToString(const UnknownJavaScriptObject());
  Expect.equals(unknownJsString, unk2);
}

testExternal() {
  var x = makeA();
  Expect.equals(plainJsString, Error.safeToString(x));

  x = makeB();
  // Gets name from constructor, regardless of minification.
  Expect.equals("Instance of 'BB'", Error.safeToString(x));

  x = makeC();
  Expect.equals(unknownJsString, Error.safeToString(x));

  x = makeD();
  Expect.equals(unknownJsString, Error.safeToString(x));

  x = makeE();
  Expect.equals("Instance of 'Liar'", Error.safeToString(x));
}

testNative() {
  var x = makeP();
  Expect.isTrue(x is Purple); // This test forces Purple to be distinguished.
  Expect.notEquals(plainJsString, Error.safeToString(x));
  Expect.notEquals(unknownJsString, Error.safeToString(x));
  Expect.notEquals(interceptorString, Error.safeToString(x));
  // And not the native class constructor.
  Expect.notEquals("Instance of 'PPPP'", Error.safeToString(x));
  expectTypeName('Purple', Error.safeToString(x));

  x = makeQ();
  print('Q:  $x  ${Error.safeToString(x)}');
  // We are going to get either the general interceptor or the JavaScript
  // constructor.
  Expect.isTrue("Instance of 'QQQQ'" == Error.safeToString(x) ||
      interceptorString == Error.safeToString(x));

  x = makeR();

  // Rascal overrides 'toString'.  The toString() call causes Rascal to be
  // distinguished.
  x.toString();
  Expect.notEquals(plainJsString, Error.safeToString(x));
  Expect.notEquals(unknownJsString, Error.safeToString(x));
  Expect.notEquals(interceptorString, Error.safeToString(x));
  // And not the native class constructor.
  Expect.notEquals("Instance of 'RRRR'", Error.safeToString(x));
  expectTypeName('Rascal', Error.safeToString(x));
}

main() {
  nativeTesting();
  setup();

  testDistinctInterceptors();
  testExternal();
  testNative();
}
