summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2019-02-18 09:56:01 +0100
committerAndreas Rumpf <rumpf_a@web.de>2019-02-18 09:56:01 +0100
commitc8e33cbb75caf21a76d379ce94b42baffbefa73f (patch)
tree2382ee25980be7fa3e89a1a5483cb78857463115
parent9e754c3b0623433380de171d25bfb862eb2f9ab7 (diff)
parent8b39551fca81e95b51393a2a8e702eebe3ba7c51 (diff)
downloadNim-c8e33cbb75caf21a76d379ce94b42baffbefa73f.tar.gz
fixed merge conflict
-rw-r--r--.travis.yml2
-rw-r--r--appveyor.yml14
-rw-r--r--compiler/jsgen.nim7
-rw-r--r--compiler/pragmas.nim2
-rw-r--r--compiler/reorder.nim2
-rw-r--r--config/nimdoc.cfg15
-rw-r--r--doc/tut1.rst108
-rw-r--r--doc/tut2.rst25
-rw-r--r--lib/js/dom.nim13
-rw-r--r--lib/pure/algorithm.nim2
-rw-r--r--lib/pure/asyncnet.nim12
-rw-r--r--lib/pure/mimetypes.nim1
-rw-r--r--lib/pure/osproc.nim2
-rw-r--r--lib/system.nim34
-rw-r--r--testament/categories.nim60
-rw-r--r--testament/important_packages.nim58
-rw-r--r--tests/async/tasyncawait.nim4
-rw-r--r--tests/js/tbasicenum.nim10
-rw-r--r--tests/js/tbasics.nim37
19 files changed, 296 insertions, 112 deletions
diff --git a/.travis.yml b/.travis.yml
index c202a1654..279da7920 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,6 +4,8 @@ language: c
 dist: xenial
 
 matrix:
+  fast_finish: true
+
   include:
     - os: linux
       env: NIM_COMPILE_TO_CPP=false
diff --git a/appveyor.yml b/appveyor.yml
index 9633bd15a..31be04d1b 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,14 +1,11 @@
 version: '{build}'
 
-cache:
-- x86_64-4.9.2-release-win32-seh-rt_v4-rev4.7z
-- sqlite-dll-win64-x64-3160200.zip
-# - i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z
-
 environment:
   MINGW_DIR: mingw64
   MINGW_URL: https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/4.9.2/threads-win32/seh/x86_64-4.9.2-release-win32-seh-rt_v4-rev4.7z/download
   MINGW_ARCHIVE: x86_64-4.9.2-release-win32-seh-rt_v4-rev4.7z
+  OPENBLAS_URL: https://sourceforge.net/projects/openblas/files/v0.3.5/OpenBLAS%200.3.5%20version.zip/download
+  OPENBLAS_ARCHIVE: OpenBLAS-0.3.5.zip
   SQLITE_URL: http://www.sqlite.org/2017/sqlite-dll-win64-x64-3160200.zip
   SQLITE_ARCHIVE: sqlite-dll-win64-x64-3160200.zip
   platform: x64
@@ -17,6 +14,11 @@ environment:
     - NIM_TEST_PACKAGES: true
     - NIM_TEST_PACKAGES: false
 
+cache:
+    - '%MINGW_ARCHIVE%'
+    - '%SQLITE_ARCHIVE%'
+    - '%OPENBLAS_ARCHIVE%'
+
 matrix:
   #allow_failures:
   #  - NIM_TEST_PACKAGES: true
@@ -31,6 +33,8 @@ install:
   - 7z x -y "%SQLITE_ARCHIVE%" -o"%CD%\DIST"> nul
   - IF not exist "%MINGW_ARCHIVE%" appveyor DownloadFile "%MINGW_URL%" -FileName "%MINGW_ARCHIVE%"
   - 7z x -y "%MINGW_ARCHIVE%" -o"%CD%\DIST"> nul
+  - IF not exist "%OPENBLAS_ARCHIVE%" appveyor DownloadFile "%OPENBLAS_URL%" -FileName "%OPENBLAS_ARCHIVE%"
+  - 7z x -y "%OPENBLAS_ARCHIVE%" -o"%CD%\DIST"> nul
   - SET PATH=%CD%\DIST\%MINGW_DIR%\BIN;%CD%\BIN;%PATH%
   - IF "%PLATFORM%" == "x64" ( copy C:\OpenSSL-Win64\libeay32.dll %CD%\BIN\libeay64.dll & copy C:\OpenSSL-Win64\libeay32.dll %CD%\BIN\libeay32.dll & copy C:\OpenSSL-Win64\libssl32.dll %CD%\BIN\libssl64.dll & copy C:\OpenSSL-Win64\libssl32.dll %CD%\BIN\libssl32.dll )
     ELSE ( copy C:\OpenSSL-Win32\libeay32.dll %CD%\BIN\libeay32.dll & copy C:\OpenSSL-Win32\libssl32.dll %CD%\BIN\libssl32.dll )
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index 8625f2fe1..65706cdfa 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -1149,7 +1149,7 @@ template isIndirect(x: PSym): bool =
   let v = x
   ({sfAddrTaken, sfGlobal} * v.flags != {} and
     #(mapType(v.typ) != etyObject) and
-    {sfImportc, sfVolatile, sfExportc} * v.flags == {} and
+    {sfImportc, sfExportc} * v.flags == {} and
     v.kind notin {skProc, skFunc, skConverter, skMethod, skIterator,
                   skConst, skTemp, skLet})
 
@@ -1235,7 +1235,7 @@ proc genProcForSymIfNeeded(p: PProc, s: PSym) =
 
 proc genCopyForParamIfNeeded(p: PProc, n: PNode) =
   let s = n.sym
-  if p.prc == s.owner or needsNoCopy(p, n): 
+  if p.prc == s.owner or needsNoCopy(p, n):
     return
   var owner = p.up
   while true:
@@ -1597,8 +1597,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
     internalError(p.config, "createVar: " & $t.kind)
     result = nil
 
-template returnType: untyped =
-  ~""
+template returnType: untyped = ~""
 
 proc genVarInit(p: PProc, v: PSym, n: PNode) =
   var
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index b1063b682..3b6f82c40 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -241,7 +241,7 @@ proc pragmaNoForward(c: PContext, n: PNode; flag=sfNoForward) =
 
   # deprecated as of 0.18.1
   message(c.config, n.info, warnDeprecated,
-          "use {.experimental: \"codeReordering.\".} instead; " &
+          "use {.experimental: \"codeReordering\".} instead; " &
           (if flag == sfNoForward: "{.noForward.}" else: "{.reorder.}") & " is deprecated")
 
 proc processCallConv(c: PContext, n: PNode) =
diff --git a/compiler/reorder.nim b/compiler/reorder.nim
index 8c4d0d307..18ec659ba 100644
--- a/compiler/reorder.nim
+++ b/compiler/reorder.nim
@@ -212,7 +212,7 @@ proc mergeSections(conf: ConfigRef; comps: seq[seq[DepN]], res: PNode) =
           # Problematic circular dependency, we arrange the nodes into
           # their original relative order and make sure to re-merge
           # consecutive type and const sections
-          var wmsg = "Circular dependency detected. reorder pragma may not be able to" &
+          var wmsg = "Circular dependency detected. `codeReordering` pragma may not be able to" &
             " reorder some nodes properely"
           when defined(debugReorder):
             wmsg &= ":\n"
diff --git a/config/nimdoc.cfg b/config/nimdoc.cfg
index cd29cbae0..c5effd04e 100644
--- a/config/nimdoc.cfg
+++ b/config/nimdoc.cfg
@@ -77,7 +77,20 @@ $content
 doc.body_toc = """
 <div class="row">
   <div class="three columns">
-  <div>
+  <div id="global-links">
+    <ul class="simple-boot">
+      <li>
+        <a href="manual.html">Manual</a>
+      </li>
+      <li>
+        <a href="lib.html">Standard library</a>
+      </li>
+      <li>
+        <a href="theindex.html">Index</a>
+      </li>
+    </ul>
+  </div>
+  <div id="searchInputDiv">
     Search: <input type="text" id="searchInput"
       onkeyup="search()" />
   </div>
diff --git a/doc/tut1.rst b/doc/tut1.rst
index a7f1b741a..161b4b904 100644
--- a/doc/tut1.rst
+++ b/doc/tut1.rst
@@ -1441,31 +1441,111 @@ string that is "useless" and replace it with "useful".
 Note: alternate ways of writing this are ``b[^8..^2] = "useful"`` or
 as ``b[11..b.len-2] = "useful"`` or as ``b[11..<b.len-1] = "useful"``.
 
+Objects
+-------
+
+The default type to pack different values together in a single
+structure with a name is the object type. An object is a value type,
+which means that when an object is assigned to a new variable all its
+components are copied as well.
+
+Each object type ``Foo`` has a constructor ``Foo(field: value, ...)``
+where all of its fields can be initialized. Unspecified fields will
+get their default value.
+
+.. code-block:: nim
+  type
+    Person = object
+      name: string
+      age: int
+
+  var person1 = Person(name: "Peter", age: 30)
+
+  echo person1.name # "Peter"
+  echo person1.age  # 30
+
+  var person2 = person1 # copy of person 1
+
+  person2.age += 14
+
+  echo person1.age # 30
+  echo person2.age # 44
+
+
+  # the order may be changed
+  let person3 = Person(age: 12, name: "Quentin")
+
+  # not every member needs to be specified
+  let person4 = Person(age: 3)
+  # unspecified members will be initialized with their default
+  # values. In this case it is the empty string.
+  doAssert person4.name == ""
+
+
+Object fields that should be visible from outside the defining module have to
+be marked with ``*``.
+
+.. code-block:: nim
+    :test: "nim c $1"
+
+  type
+    Person* = object # the type is visible from other modules
+      name*: string  # the field of this type is visible from other modules
+      age*: int
+
 Tuples
 ------
 
-A tuple type defines various named *fields* and an *order* of the fields.
-The constructor ``()`` can be used to construct tuples. The order of the
-fields in the constructor must match the order in the tuple's definition.
-Different tuple-types are *equivalent* if they specify fields of
+Tuples are very much like what you have seen so far from objects. They
+are value types where the assignment operator copies each component.
+Unlike object types though, tuple types are structurally typed,
+meaning different tuple-types are *equivalent* if they specify fields of
 the same type and of the same name in the same order.
 
-The assignment operator for tuples copies each component. The notation
-``t.field`` is used to access a tuple's field. Another notation is
+The constructor ``()`` can be used to construct tuples. The order of the
+fields in the constructor must match the order in the tuple's
+definition. But unlike objects, a name for the tuple type may not be
+used here.
+
+
+Like the object type the notation ``t.field`` is used to access a
+tuple's field. Another notation that is not available for objects is
 ``t[i]`` to access the ``i``'th field. Here ``i`` must be a constant
 integer.
 
 .. code-block:: nim
     :test: "nim c $1"
-
   type
-    Person = tuple[name: string, age: int] # type representing a person:
-                                           # a person consists of a name
-                                           # and an age
+    # type representing a person:
+    # A person consists of a name and an age.
+    Person = tuple
+      name: string
+      age: int
+
+    # Alternative syntax for an equivalent type.
+    PersonX = tuple[name: string, age: int]
+
+    # anonymous field syntax
+    PersonY = (string, int)
+
   var
     person: Person
+    personX: PersonX
+    personY: PersonY
+
   person = (name: "Peter", age: 30)
-  # the same, but less readable:
+  # Person and PersonX are equivalent
+  personX = person
+
+  # Create a tuple with anonymous fields:
+  personY = ("Peter", 30)
+
+  # A tuple with anonymous fields is compatible with a tuple that has
+  # field names.
+  person = personY
+  personY = person
+
+  # Usually used for short tuple initialization syntax
   person = ("Peter", 30)
 
   echo person.name # "Peter"
@@ -1484,10 +1564,6 @@ integer.
   # --> Error: type mismatch: got (tuple[street: string, number: int])
   #     but expected 'Person'
 
-  # The following works because the field names and types are the same.
-  var teacher: tuple[name: string, age: int] = ("Mark", 42)
-  person = teacher
-
 Even though you don't need to declare a type for a tuple to use it, tuples
 created with different field names will be considered different objects despite
 having the same field types.
@@ -1519,6 +1595,8 @@ variables! For example:
   echo badname
   echo badext
 
+Fields of tuples are always public, they don't need to be explicity
+marked to be exported, unlike for example fields in an object type.
 
 Reference and pointer types
 ---------------------------
diff --git a/doc/tut2.rst b/doc/tut2.rst
index d0c6e7247..4c1ec5747 100644
--- a/doc/tut2.rst
+++ b/doc/tut2.rst
@@ -40,18 +40,16 @@ and more efficient code. In particular, preferring composition over inheritance
 is often the better design.
 
 
-Objects
--------
-
-Like tuples, objects are a means to pack different values together in a
-structured way. However, objects provide many features that tuples do not:
-They provide inheritance and information hiding. Because objects encapsulate
-data, the ``T()`` object constructor should only be used internally and the
-programmer should provide a proc to initialize the object (this is called
-a *constructor*).
+Inheritance
+-----------
 
-Objects have access to their type at runtime. There is an
-``of`` operator that can be used to check the object's type:
+Inheritance in Nim is entirely optional. To enable inheritance with
+runtime type information the object needs to inherit from
+``RootObj``.  This can be done directly, or indirectly by
+inheriting from an object that inherits from ``RootObj``.  Usually
+types with inheritance are also marked as ``ref`` types even though
+this isn't strictly enforced. To check at runtime if an object is of a certain
+type, the ``of`` operator can be used.
 
 .. code-block:: nim
     :test: "nim c $1"
@@ -71,11 +69,6 @@ Objects have access to their type at runtime. There is an
   student = Student(name: "Anton", age: 5, id: 2)
   echo student[]
 
-Object fields that should be visible from outside the defining module have to
-be marked by ``*``. In contrast to tuples, different object types are
-never *equivalent*. New object types can only be defined within a type
-section.
-
 Inheritance is done with the ``object of`` syntax. Multiple inheritance is
 currently not supported. If an object type has no suitable ancestor, ``RootObj``
 can be used as its ancestor, but this is only a convention. Objects that have
diff --git a/lib/js/dom.nim b/lib/js/dom.nim
index 9d6cd9152..3c6d65d8a 100644
--- a/lib/js/dom.nim
+++ b/lib/js/dom.nim
@@ -192,7 +192,7 @@ type
 
   Element* = ref ElementObj
   ElementObj {.importc.} = object of NodeObj
-    classList*: Classlist
+    classList*: ClassList
     checked*: bool
     defaultChecked*: bool
     defaultValue*: cstring
@@ -1183,9 +1183,10 @@ proc contains*(c: ClassList, class: cstring): bool
 proc toggle*(c: ClassList, class: cstring)
 
 # Style "methods"
-proc getAttribute*(s: Style, attr: cstring, caseSensitive=false): cstring
-proc removeAttribute*(s: Style, attr: cstring, caseSensitive=false)
-proc setAttribute*(s: Style, attr, value: cstring, caseSensitive=false)
+proc getPropertyValue*(s: Style, property: cstring): cstring
+proc removeProperty*(s: Style, property: cstring)
+proc setProperty*(s: Style, property, value: cstring, priority = "")
+proc getPropertyPriority*(s: Style, property: cstring): cstring
 
 # Event "methods"
 proc preventDefault*(ev: Event)
@@ -1267,6 +1268,10 @@ proc inViewport*(el: Node): bool =
            rect.right <= clientWidth().float
 
 proc scrollTop*(e: Node): int {.importcpp: "#.scrollTop", nodecl.}
+proc scrollLeft*(e: Node): int {.importcpp: "#.scrollLeft", nodecl.}
+proc scrollHeight*(e: Node): int {.importcpp: "#.scrollHeight", nodecl.}
+proc scrollWidth*(e: Node): int {.importcpp: "#.scrollWidth", nodecl.}
 proc offsetHeight*(e: Node): int {.importcpp: "#.offsetHeight", nodecl.}
+proc offsetWidth*(e: Node): int {.importcpp: "#.offsetWidth", nodecl.}
 proc offsetTop*(e: Node): int {.importcpp: "#.offsetTop", nodecl.}
 proc offsetLeft*(e: Node): int {.importcpp: "#.offsetLeft", nodecl.}
diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim
index 8c8838ed2..b346c7a44 100644
--- a/lib/pure/algorithm.nim
+++ b/lib/pure/algorithm.nim
@@ -511,7 +511,7 @@ func isSorted*[T](a: openArray[T],
                  order = SortOrder.Ascending): bool =
   ## Checks to see whether ``a`` is already sorted in ``order``
   ## using ``cmp`` for the comparison. Parameters identical
-  ## to ``sort``.
+  ## to ``sort``. Requires O(n) time.
   ##
   ## **See also:**
   ## * `isSorted proc<#isSorted,openArray[T]>`_
diff --git a/lib/pure/asyncnet.nim b/lib/pure/asyncnet.nim
index 1c0681fad..56bda737a 100644
--- a/lib/pure/asyncnet.nim
+++ b/lib/pure/asyncnet.nim
@@ -166,6 +166,18 @@ proc newAsyncSocket*(domain: Domain = AF_INET, sockType: SockType = SOCK_STREAM,
     raiseOSError(osLastError())
   result = newAsyncSocket(fd, domain, sockType, protocol, buffered)
 
+proc getLocalAddr*(socket: AsyncSocket): (string, Port) =
+  ## Get the socket's local address and port number.
+  ##
+  ## This is high-level interface for `getsockname`:idx:.
+  getLocalAddr(socket.fd, socket.domain)
+
+proc getPeerAddr*(socket: AsyncSocket): (string, Port) =
+  ## Get the socket's peer address and port number.
+  ##
+  ## This is high-level interface for `getpeername`:idx:.
+  getPeerAddr(socket.fd, socket.domain)
+
 proc newAsyncSocket*(domain, sockType, protocol: cint,
     buffered = true): AsyncSocket =
   ## Creates a new asynchronous socket.
diff --git a/lib/pure/mimetypes.nim b/lib/pure/mimetypes.nim
index 57ea82527..97ebd35c2 100644
--- a/lib/pure/mimetypes.nim
+++ b/lib/pure/mimetypes.nim
@@ -1906,6 +1906,7 @@ func getExt*(mimedb: MimeDB, mimetype: string, default = "txt"): string =
   for e, m in mimedb.mimes:
     if m == mimeLowered:
       result = e
+      break
 
 func register*(mimedb: var MimeDB, ext: string, mimetype: string) =
   ## Adds ``mimetype`` to the ``mimedb``.
diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim
index 78f9a06eb..9502b679a 100644
--- a/lib/pure/osproc.nim
+++ b/lib/pure/osproc.nim
@@ -224,7 +224,7 @@ proc execProcesses*(cmds: openArray[string],
                     beforeRunEvent: proc(idx: int) = nil,
                     afterRunEvent: proc(idx: int, p: Process) = nil): int
                     {.rtl, extern: "nosp$1",
-                    tags: [ExecIOEffect, TimeEffect, ReadEnvEffect, RootEffect]} =
+                    tags: [ExecIOEffect, TimeEffect, ReadEnvEffect, RootEffect].} =
   ## executes the commands `cmds` in parallel. Creates `n` processes
   ## that execute in parallel. The highest (absolute) return value of all processes
   ## is returned. Runs `beforeRunEvent` before running each command.
diff --git a/lib/system.nim b/lib/system.nim
index b75be3df5..268d6ccd3 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -904,37 +904,51 @@ proc chr*(u: range[0..255]): char {.magic: "Chr", noSideEffect.}
 # built-in operators
 
 when not defined(JS):
-  proc ze*(x: int8): int {.magic: "Ze8ToI", noSideEffect.}
+  proc ze*(x: int8): int {.magic: "Ze8ToI", noSideEffect, deprecated.}
     ## zero extends a smaller integer type to ``int``. This treats `x` as
     ## unsigned.
-  proc ze*(x: int16): int {.magic: "Ze16ToI", noSideEffect.}
+    ## **Deprecated since version 0.19.9**: Use unsigned integers instead.
+
+  proc ze*(x: int16): int {.magic: "Ze16ToI", noSideEffect, deprecated.}
     ## zero extends a smaller integer type to ``int``. This treats `x` as
     ## unsigned.
+    ## **Deprecated since version 0.19.9**: Use unsigned integers instead.
 
-  proc ze64*(x: int8): int64 {.magic: "Ze8ToI64", noSideEffect.}
+  proc ze64*(x: int8): int64 {.magic: "Ze8ToI64", noSideEffect, deprecated.}
     ## zero extends a smaller integer type to ``int64``. This treats `x` as
     ## unsigned.
-  proc ze64*(x: int16): int64 {.magic: "Ze16ToI64", noSideEffect.}
+    ## **Deprecated since version 0.19.9**: Use unsigned integers instead.
+
+  proc ze64*(x: int16): int64 {.magic: "Ze16ToI64", noSideEffect, deprecated.}
     ## zero extends a smaller integer type to ``int64``. This treats `x` as
     ## unsigned.
+    ## **Deprecated since version 0.19.9**: Use unsigned integers instead.
 
-  proc ze64*(x: int32): int64 {.magic: "Ze32ToI64", noSideEffect.}
+  proc ze64*(x: int32): int64 {.magic: "Ze32ToI64", noSideEffect, deprecated.}
     ## zero extends a smaller integer type to ``int64``. This treats `x` as
     ## unsigned.
-  proc ze64*(x: int): int64 {.magic: "ZeIToI64", noSideEffect.}
+    ## **Deprecated since version 0.19.9**: Use unsigned integers instead.
+
+  proc ze64*(x: int): int64 {.magic: "ZeIToI64", noSideEffect, deprecated.}
     ## zero extends a smaller integer type to ``int64``. This treats `x` as
     ## unsigned. Does nothing if the size of an ``int`` is the same as ``int64``.
     ## (This is the case on 64 bit processors.)
+    ## **Deprecated since version 0.19.9**: Use unsigned integers instead.
 
-  proc toU8*(x: int): int8 {.magic: "ToU8", noSideEffect.}
+  proc toU8*(x: int): int8 {.magic: "ToU8", noSideEffect, deprecated.}
     ## treats `x` as unsigned and converts it to a byte by taking the last 8 bits
     ## from `x`.
-  proc toU16*(x: int): int16 {.magic: "ToU16", noSideEffect.}
+    ## **Deprecated since version 0.19.9**: Use unsigned integers instead.
+
+  proc toU16*(x: int): int16 {.magic: "ToU16", noSideEffect, deprecated.}
     ## treats `x` as unsigned and converts it to an ``int16`` by taking the last
     ## 16 bits from `x`.
-  proc toU32*(x: int64): int32 {.magic: "ToU32", noSideEffect.}
+    ## **Deprecated since version 0.19.9**: Use unsigned integers instead.
+
+  proc toU32*(x: int64): int32 {.magic: "ToU32", noSideEffect, deprecated.}
     ## treats `x` as unsigned and converts it to an ``int32`` by taking the
     ## last 32 bits from `x`.
+    ## **Deprecated since version 0.19.9**: Use unsigned integers instead.
 
 # integer calculations:
 proc `+`*(x: int): int {.magic: "UnaryPlusI", noSideEffect.}
@@ -3877,7 +3891,7 @@ when false:
     macro payload: typed {.gensym.} = blk
     payload()
 
-when hasAlloc:
+when hasAlloc or defined(nimscript):
   proc insert*(x: var string, item: string, i = 0.Natural) {.noSideEffect.} =
     ## inserts `item` into `x` at position `i`.
     var xl = x.len
diff --git a/testament/categories.nim b/testament/categories.nim
index 77769743d..c7365e8fd 100644
--- a/testament/categories.nim
+++ b/testament/categories.nim
@@ -471,7 +471,8 @@ proc getPackageDir(package: string): string =
   else:
     result = commandOutput[0].string
 
-iterator listPackages(filter: PackageFilter): tuple[name, url, cmd: string] =
+iterator listPackages(filter: PackageFilter):
+                      tuple[name, url, cmd: string, hasDeps: bool] =
   const defaultCmd = "nimble test"
   let packageList = parseFile(packageIndex)
   for package in packageList.items:
@@ -482,12 +483,12 @@ iterator listPackages(filter: PackageFilter): tuple[name, url, cmd: string] =
         case filter
         of pfCoreOnly:
           if "nim-lang" in normalize(url):
-            yield (name, url, defaultCmd)
+            yield (name, url, defaultCmd, false)
         of pfExtraOnly:
-          for n, cmd, commit in important_packages.packages.items:
-            if name == n: yield (name, url, cmd)
+          for n, cmd, commit, hasDeps in important_packages.packages.items:
+            if name == n: yield (name, url, cmd, hasDeps)
         of pfAll:
-          yield (name, url, defaultCmd)
+          yield (name, url, defaultCmd, false)
 
 proc makeSupTest(test, options: string, cat: Category): TTest =
   result.cat = cat
@@ -506,32 +507,47 @@ proc testNimblePackages(r: var TResults, cat: Category, filter: PackageFilter) =
 
   let packageFileTest = makeSupTest("PackageFileParsed", "", cat)
   var keepDir = false
+  var packagesDir = "pkgstemp"
   try:
-    for name, url, cmd in listPackages(filter):
+    for name, url, cmd, hasDep in listPackages(filter):
       var test = makeSupTest(url, "", cat)
-      let buildPath = "pkgstemp" / name
-      let installProcess = startProcess("git", "", ["clone", url, buildPath])
-      let installStatus = waitForExitEx(installProcess)
-      installProcess.close
-      if installStatus != QuitSuccess:
-        r.addResult(test, targetC, "", "", reInstallFailed)
+      let buildPath = packagesDir / name
+      if not existsDir(buildPath):
+        if hasDep:
+          let nimbleProcess = startProcess("nimble", "", ["install", "-y", name],
+                                           options = {poUsePath, poStdErrToStdOut})
+          let nimbleStatus = waitForExitEx(nimbleProcess)
+          nimbleProcess.close
+          if nimbleStatus != QuitSuccess:
+            r.addResult(test, targetC, "", "", reInstallFailed)
+            keepDir = true
+            continue
+
+        let installProcess = startProcess("git", "", ["clone", url, buildPath],
+                                          options = {poUsePath, poStdErrToStdOut})
+        let installStatus = waitForExitEx(installProcess)
+        installProcess.close
+        if installStatus != QuitSuccess:
+          r.addResult(test, targetC, "", "", reInstallFailed)
+          keepDir = true
+          continue
+
+      let cmdArgs = parseCmdLine(cmd)
+      let buildProcess = startProcess(cmdArgs[0], buildPath, cmdArgs[1..^1],
+                                      options = {poUsePath, poStdErrToStdOut})
+      let buildStatus = waitForExitEx(buildProcess)
+      buildProcess.close
+      if buildStatus != QuitSuccess:
+        r.addResult(test, targetC, "", "", reBuildFailed)
         keepDir = true
       else:
-        let cmdArgs = parseCmdLine(cmd)
-        let buildProcess = startProcess(cmdArgs[0], buildPath, cmdArgs[1..^1])
-        let buildStatus = waitForExitEx(buildProcess)
-        buildProcess.close
-        if buildStatus != QuitSuccess:
-          r.addResult(test, targetC, "", "", reBuildFailed)
-          keepDir = true
-        else:
-          r.addResult(test, targetC, "", "", reSuccess)
+        r.addResult(test, targetC, "", "", reSuccess)
     r.addResult(packageFileTest, targetC, "", "", reSuccess)
   except JsonParsingError:
     echo("[Warning] - Cannot run nimble tests: Invalid package file.")
     r.addResult(packageFileTest, targetC, "", "", reBuildFailed)
   finally:
-    if not keepDir: removeDir("pkgstemp")
+    if not keepDir: removeDir(packagesDir)
 
 
 # ----------------------------------------------------------------------------
diff --git a/testament/important_packages.nim b/testament/important_packages.nim
index fbb3edaa8..e4cbec7f8 100644
--- a/testament/important_packages.nim
+++ b/testament/important_packages.nim
@@ -1,28 +1,44 @@
 import strutils
 
-template pkg(name: string; cmd = "nimble test"; version = ""): untyped =
-  packages.add((name, cmd, version))
+template pkg(name: string; cmd = "nimble test"; version = ""; hasDeps = false): untyped =
+  packages.add((name, cmd, version, hasDeps))
 
-var packages*: seq[tuple[name, cmd, version: string]] = @[]
+var packages*: seq[tuple[name, cmd, version: string; hasDeps: bool]] = @[]
 
-pkg "karax"
-pkg "cligen"
+
+pkg "arraymancer", "nim c src/arraymancer.nim", "", true
+pkg "ast_pattern_matching", "nim c tests/test1.nim"
+pkg "c2nim"
+pkg "cligen", "nim c -o:cligenn cligen.nim"
+pkg "compactdict", "nim c tests/test1.nim"
+pkg "criterion"
+pkg "docopt"
+pkg "gara", "nim c tests/test_gara.nim"
 pkg "glob"
-#pkg "regex"
-pkg "freeimage", "nim c freeimage.nim"
-pkg "zero_functional"
-pkg "nimpy", "nim c nimpy.nim"
-#pkg "nimongo", "nimble test_ci"
+pkg "gnuplot"
+pkg "hts", "nim c tests/all.nim"
 pkg "inim"
-
-pkg "sdl1", "nim c src/sdl.nim"
+pkg "itertools", "nim doc src/itertools.nim"
 pkg "iterutils"
-pkg "gnuplot"
-pkg "c2nim"
-
-#[
-    arraymancer
-    nimpb
-    jester
-    nimx
-]#
+pkg "karax", "nim c tests/tester.nim"
+pkg "loopfusion"
+pkg "nake", "nim c nakefile.nim"
+pkg "neo", "nim c -d:blas=openblas tests/all.nim", "", true
+pkg "nigui", "nim c -o:niguii src/nigui.nim"
+pkg "NimData", "nim c -o:nimdataa src/nimdata.nim", "", true
+pkg "nimes", "nim c src/nimes.nim", "", true
+pkg "nimgame2", "nim c nimgame2/nimgame.nim", "", true
+pkg "nimongo", "nimble test_ci", "", true
+pkg "nimpy", "nim c -o:nimpyy nimpy.nim"
+pkg "nimsl", "nim c test.nim"
+pkg "nimx", "nim c --threads:on test/main.nim", "", true
+pkg "parsetoml"
+pkg "patty"
+pkg "plotly", "nim c examples/all.nim", "", true
+pkg "protobuf", "nim c -o:protobuff src/protobuf.nim", "", true
+pkg "regex", "nim c src/regex"
+pkg "rosencrantz", "nim c -o:rsncntz rosencrantz.nim"
+pkg "sdl1", "nim c src/sdl.nim"
+pkg "sdl2_nim", "nim c sdl2/sdl.nim"
+pkg "stint", "nim c -o:stintt stint.nim"
+pkg "zero_functional", "nim c test.nim"
diff --git a/tests/async/tasyncawait.nim b/tests/async/tasyncawait.nim
index 1e6cf3761..063c8317c 100644
--- a/tests/async/tasyncawait.nim
+++ b/tests/async/tasyncawait.nim
@@ -26,6 +26,10 @@ proc launchSwarm(port: Port) {.async.} =
 proc readMessages(client: AsyncFD) {.async.} =
   # wrapping the AsyncFd into a AsyncSocket object
   var sockObj = newAsyncSocket(client)
+  var (ipaddr, port) = sockObj.getPeerAddr()
+  doAssert ipaddr == "127.0.0.1"
+  (ipaddr, port) = sockObj.getLocalAddr()
+  doAssert ipaddr == "127.0.0.1"
   while true:
     var line = await recvLine(sockObj)
     if line == "":
diff --git a/tests/js/tbasicenum.nim b/tests/js/tbasicenum.nim
deleted file mode 100644
index a9e9ce2da..000000000
--- a/tests/js/tbasicenum.nim
+++ /dev/null
@@ -1,10 +0,0 @@
-discard """
-  output: "ABCDC"
-"""
-
-type
-  MyEnum = enum
-    A,B,C,D
-# trick the optimizer with an seq:
-var x = @[A,B,C,D]
-echo x[0],x[1],x[2],x[3],MyEnum(2)
\ No newline at end of file
diff --git a/tests/js/tbasics.nim b/tests/js/tbasics.nim
new file mode 100644
index 000000000..0c8d33e7f
--- /dev/null
+++ b/tests/js/tbasics.nim
@@ -0,0 +1,37 @@
+discard """
+  output: '''ABCDC
+1
+14
+ok'''
+"""
+
+type
+  MyEnum = enum
+    A,B,C,D
+# trick the optimizer with an seq:
+var x = @[A,B,C,D]
+echo x[0],x[1],x[2],x[3],MyEnum(2)
+
+# bug #10651
+
+var xa: seq[int]
+var ya = @[1,2]
+xa &= ya
+echo xa[0]
+
+proc test =
+  var yup: seq[int]
+  try:
+    yup.add 14
+    echo yup.pop
+  finally:
+    discard
+
+test()
+
+when true:
+  var a: seq[int]
+
+  a.setLen(0)
+
+  echo "ok"
\ No newline at end of file