diff --git a/Data/String.hs b/Data/String.hs
--- a/Data/String.hs
+++ b/Data/String.hs
@@ -37,8 +37,26 @@
 import Data.Functor.Identity (Identity (Identity))
 import Data.List (lines, words, unlines, unwords)
 
--- | Class for string-like datastructures; used by the overloaded string
---   extension (-XOverloadedStrings in GHC).
+-- | `IsString` is used in combination with the @-XOverloadedStrings@
+-- language extension to convert the literals to different string types.
+--
+-- For example, if you use the [text](https://hackage.haskell.org/package/text) package,
+-- you can say
+--
+-- @
+-- {-# LANGUAGE OverloadedStrings  #-}
+--
+-- myText = "hello world" :: Text
+-- @
+--
+-- Internally, the extension will convert this to the equivalent of
+--
+-- @
+-- myText = fromString @Text ("hello world" :: String)
+-- @
+--
+-- __Note:__ You can use @fromString@ in normal code as well,
+-- but the usual performance/memory efficiency problems with 'String' apply.
 class IsString a where
     fromString :: String -> a
 
diff --git a/GHC/Base.hs b/GHC/Base.hs
--- a/GHC/Base.hs
+++ b/GHC/Base.hs
@@ -1493,10 +1493,42 @@
 -- Type Char and String
 ----------------------------------------------
 
--- | A 'String' is a list of characters.  String constants in Haskell are values
--- of type 'String'.
+-- | 'String' is an alias for a list of characters.
 --
--- See "Data.List" for operations on lists.
+-- String constants in Haskell are values of type 'String'.
+-- That means if you write a string literal like @"hello world"@,
+-- it will have the type @[Char]@, which is the same as @String@.
+--
+-- __Note:__ You can ask the compiler to automatically infer different types
+-- with the @-XOverloadedStrings@ language extension, for example
+--  @"hello world" :: Text@. See t'Data.String.IsString' for more information.
+--
+-- Because @String@ is just a list of characters, you can use normal list functions
+-- to do basic string manipulation. See "Data.List" for operations on lists.
+--
+-- === __Performance considerations__
+--
+-- @[Char]@ is a relatively memory-inefficient type.
+-- It is a linked list of boxed word-size characters, internally it looks something like:
+--
+-- > ╭─────┬───┬──╮  ╭─────┬───┬──╮  ╭─────┬───┬──╮  ╭────╮
+-- > │ (:) │   │ ─┼─>│ (:) │   │ ─┼─>│ (:) │   │ ─┼─>│ [] │
+-- > ╰─────┴─┼─┴──╯  ╰─────┴─┼─┴──╯  ╰─────┴─┼─┴──╯  ╰────╯
+-- >         v               v               v
+-- >        'a'             'b'             'c'
+--
+-- The @String@ "abc" will use @5*3+1 = 16@ (in general @5n+1@)
+-- words of space in memory.
+--
+-- Furthermore, operations like '(++)' (string concatenation) are @O(n)@
+-- (in the left argument).
+--
+-- For historical reasons, the @base@ library uses @String@ in a lot of places
+-- for the conceptual simplicity, but library code dealing with user-data
+-- should use the [text](https://hackage.haskell.org/package/text)
+-- package for Unicode text, or the the
+-- [bytestring](https://hackage.haskell.org/package/bytestring) package
+-- for binary data.
 type String = [Char]
 
 unsafeChr :: Int -> Char
diff --git a/GHC/Unicode/Internal/Char/DerivedCoreProperties.hs b/GHC/Unicode/Internal/Char/DerivedCoreProperties.hs
--- a/GHC/Unicode/Internal/Char/DerivedCoreProperties.hs
+++ b/GHC/Unicode/Internal/Char/DerivedCoreProperties.hs
@@ -1,5 +1,5 @@
 -- DO NOT EDIT: This file is automatically generated by the internal tool ucd2haskell,
--- with data from: https://www.unicode.org/Public/15.0.0/ucd/DerivedCoreProperties.txt.
+-- with data from: https://www.unicode.org/Public/15.1.0/ucd/DerivedCoreProperties.txt.
 
 {-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE MagicHash #-}
diff --git a/GHC/Unicode/Internal/Char/UnicodeData/GeneralCategory.hs b/GHC/Unicode/Internal/Char/UnicodeData/GeneralCategory.hs
# file too large to diff: GHC/Unicode/Internal/Char/UnicodeData/GeneralCategory.hs
diff --git a/GHC/Unicode/Internal/Char/UnicodeData/SimpleLowerCaseMapping.hs b/GHC/Unicode/Internal/Char/UnicodeData/SimpleLowerCaseMapping.hs
--- a/GHC/Unicode/Internal/Char/UnicodeData/SimpleLowerCaseMapping.hs
+++ b/GHC/Unicode/Internal/Char/UnicodeData/SimpleLowerCaseMapping.hs
@@ -1,5 +1,5 @@
 -- DO NOT EDIT: This file is automatically generated by the internal tool ucd2haskell,
--- with data from: https://www.unicode.org/Public/15.0.0/ucd/UnicodeData.txt.
+-- with data from: https://www.unicode.org/Public/15.1.0/ucd/UnicodeData.txt.
 
 {-# LANGUAGE NoImplicitPrelude, LambdaCase #-}
 {-# OPTIONS_HADDOCK hide #-}
diff --git a/GHC/Unicode/Internal/Char/UnicodeData/SimpleTitleCaseMapping.hs b/GHC/Unicode/Internal/Char/UnicodeData/SimpleTitleCaseMapping.hs
--- a/GHC/Unicode/Internal/Char/UnicodeData/SimpleTitleCaseMapping.hs
+++ b/GHC/Unicode/Internal/Char/UnicodeData/SimpleTitleCaseMapping.hs
@@ -1,5 +1,5 @@
 -- DO NOT EDIT: This file is automatically generated by the internal tool ucd2haskell,
--- with data from: https://www.unicode.org/Public/15.0.0/ucd/UnicodeData.txt.
+-- with data from: https://www.unicode.org/Public/15.1.0/ucd/UnicodeData.txt.
 
 {-# LANGUAGE NoImplicitPrelude, LambdaCase #-}
 {-# OPTIONS_HADDOCK hide #-}
diff --git a/GHC/Unicode/Internal/Char/UnicodeData/SimpleUpperCaseMapping.hs b/GHC/Unicode/Internal/Char/UnicodeData/SimpleUpperCaseMapping.hs
--- a/GHC/Unicode/Internal/Char/UnicodeData/SimpleUpperCaseMapping.hs
+++ b/GHC/Unicode/Internal/Char/UnicodeData/SimpleUpperCaseMapping.hs
@@ -1,5 +1,5 @@
 -- DO NOT EDIT: This file is automatically generated by the internal tool ucd2haskell,
--- with data from: https://www.unicode.org/Public/15.0.0/ucd/UnicodeData.txt.
+-- with data from: https://www.unicode.org/Public/15.1.0/ucd/UnicodeData.txt.
 
 {-# LANGUAGE NoImplicitPrelude, LambdaCase #-}
 {-# OPTIONS_HADDOCK hide #-}
diff --git a/GHC/Unicode/Internal/Version.hs b/GHC/Unicode/Internal/Version.hs
--- a/GHC/Unicode/Internal/Version.hs
+++ b/GHC/Unicode/Internal/Version.hs
@@ -19,8 +19,8 @@
 import {-# SOURCE #-} Data.Version
 
 -- | Version of Unicode standard used by @base@:
--- [15.0.0](https://www.unicode.org/versions/Unicode15.0.0/).
+-- [15.1.0](https://www.unicode.org/versions/Unicode15.1.0/).
 --
 -- @since 4.15.0.0
 unicodeVersion :: Version
-unicodeVersion = makeVersion [15, 0, 0]
+unicodeVersion = makeVersion [15, 1, 0]
diff --git a/base.cabal b/base.cabal
--- a/base.cabal
+++ b/base.cabal
@@ -1,6 +1,6 @@
 cabal-version:  3.0
 name:           base
-version:        4.18.1.0
+version:        4.18.2.0
 -- NOTE: Don't forget to update ./changelog.md
 
 license:        BSD-3-Clause
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,9 @@
 # Changelog for [`base` package](http://hackage.haskell.org/package/base)
 
+## 4.18.2.0 *January 2024*
+  * Update to [Unicode 15.1.0](https://www.unicode.org/versions/Unicode15.1.0/).
+  * Improve String & IsString documentation.
+
 ## 4.18.1.0 *September 2023*
 
    * Add missing int64/word64-to-double/float rules ([CLC Proposal #203](https://github.com/haskell/core-libraries-committee/issues/203))
diff --git a/jsbits/base.js b/jsbits/base.js
--- a/jsbits/base.js
+++ b/jsbits/base.js
@@ -826,8 +826,7 @@
   }
   const e = d.readSync();
 
-  if (!dst_a.arr) dst_a.arr = [];
-  dst_a.arr[dst_o*2] = [e,0];
+  PUT_ADDR(dst_a,dst_o*2,e,0);
   return 0;
 }
 
