🌸
357 subscribers
127 photos
17 videos
197 links
记录一些 学习笔记,工具,和其它奇怪的东西
Download Telegram
学到两个新词:
Elegant degradation 优雅退化
Progressive enhancement 渐进式增强
alpha-value 如果告诉我是 alpha channel 倒很好理解。如果说成是 transparency,每次都要在脑子里想一想。

因为,100%透明 = 不透明,而不是“完全透明”,0% 透明 = 完全透明 🤯

如果这里说成 opacity,100% 不透明 = 不透明,0% 不透明 = 完全透明。感觉会更符合直觉(
👍2
JavaScript NaN 捡屎

NaN 是 Not a Number 的缩写,如果这么理解,很快会发现 typeof NaN === 'number'

比较 NaN === NaN,结果 false,这说明 "Not a Number" not "Not a Number",但它确实是 number,这有点反直觉

---
我更倾向 JS NaN 是指 "Not a NaN”:试着检查一个值是否为 NaN,isNaN(NaN) === true,这很好,但很快又会发现 isNaN('foo') === trueisNaN([]) === true

在比较时,将关注点放在了 NaN,而不是 Number 上,或许它应该是一个独立类型,毕竟它作为独立属性出现在 top-level scope 中,而不像其它语言那样使用 float('nan')Float::NAN 等形式表示

好在,Number.isNaN() 被加到了 ES6,它只检查一个值是否 "Not a NaN",而不是 "Not a Number",“不是数字”的东西很多,而 NaN 只是 NaN

这并不是全部,JavaScript 中还有许多为了 backwards compatibility 而保留至今的糟粕设计,如在一众语言中 pow(1, Infinity) == 1,而 JS 确是 NaN;如从 Java 1.0 引进的 Date 至今也仍在使用,而早在 JDK 1.1,Date 中的很多方法就被废弃了

---
UPDATED:调整了下叙述逻辑

#屎前考古
两个 delta compression 算法

Bsdiff:https://github.com/mendsley/bsdiff
VCDIFF (RFC 3284):https://github.com/google/open-vcdiff

Bsdiff 基于 suffix array 编码数据,性能上优于 VCDIFF。

#tools
选择视频编解码器

了解了下各个 codec,从编码质量和压缩率来看,目前开放格式里最好的选择就是 WebM/AV1/Opus 这组了,专利格式则是 MP4/HEVC/AAC

不过 AV1 目前并未得到浏览器广泛支持,就连硬解在各个平台上都还不太支持。考虑上这点的话,WebM/VP9/Opus 会更具有吸引力。

尽管如此,如果有可能,始终需要为最坏情况准备好 MP4/AVC (H.264)/AAC 的 fallback 选项。

#learning
HTTP/2 Server Push 细节

HTTP/2 push cache 独立于 HTTP cache,由 server 推送的资源,仅在使用后进入 HTTP cache 并从 push cache 中移除,在推送时也不会检查其 Cache-Control header。

它基于 connection,若 connection closed,则 push cache 消失。由于 HTTP/2 中的一个 connection 除了被多个 requests 复用,还可以在多个 pages 间共享,因此 push cache 也会相应得到共享。这甚至意味着,它可以在具有同一 IP、同一 cert 的跨多个 origin 间共享缓存(即使包含任何应用状态)。

push cache 与其它一众 cache 相比,具有最低的 priority,若 pushed resource 已出现在 HTTP cache 且尚未过期,则使用“较旧的” HTTP cache,若该 resource 仍在传输,则浏览器应该发送一个 CANCEL 或 REFUSED_STREAM frame 以终止 stream。

另外,出于隐私目的,浏览器可能会为带有 credentials 和未带有它的 requests 创建两个独立的 connection,这里的 credentials 可能是 Cookies、HTTP authentication 或 Client certificate。

#learning
刚刚读文章发现两个有意思的写法(但没用!)

false.true = ''

(function () { return arguments.callee })()()


上面两个在 non-strict mode 下都可以运行。想了想第二个可以实现匿名函数递归,不过一般不用 arguments.callee。
发现不同浏览器对 AudioWorklet 支持都多少有点问题,比如 Chrome/Edge 不会在 DevTools Network 记录 audioWorklet.addModule() 的请求,包括后续 import 的模块,这是个 BUG,Firefox 正常。

Firefox 不支持在 AudioWorkletNode 中 import ES6 modules,Chrome/Edge 支持。不过 AudioWorklet Wasm 支持在 Chrome/Edge、Firefox 都挺好。

至于 Safari,我的几个 demo 都跑不起来,emm准确说是跑起来了,也没报错,但就是没声,我也懒得调了。
A visual depiction of glyph metrics

src, src #learning
Go 1.18.4 泛型支持还是有点问题,带 chan 的 union type 自动推断不出来。需要先 any(),再用子类型 T 手动构造
Forwarded from r0 Crew (Channel)
IDA Pro 8.0 released!

* Golang 1.18
* iOS 16 dyld shared cache support
* ARC decompiler
* Better firmware analysis
* FLAIR pattern generator (makepat)

https://hex-rays.com/products/ida/news/8_0/
Chrome 104 现支持 HEVC 硬解

刚刚发布的 Chrome 104 支持了 HEVC 硬解,但目前需要手动开启,在启动时添加 --args --enable-features=PlatformHEVCDecoderSupport 参数。可以使用 https://h265.webmfiles.org/embed-h265-video.php 测试是否成功。

该功能由字节跳动开发,并提交给 Chromium,使用的是操作系统解码能力(Windows D3D11,macOS VideoToolbox),因此不需要交专利费。由于 Windows 7 以下系统仅支持 VDA Decoder,因此不支持 HEVC 硬解。

此外,部分网站通过浏览器 UA 检查是否支持 HEVC,如 Bilibili,因此除添加上述参数外,还需要修改 UA 为先前已经支持的其它浏览器,如 Safari。

ref:
https://v2ex.com/t/870362
https://github.com/StaZhu/enable-chromium-hevc-hardware-decoding
👍1
macOS 的文件单位好混乱,文件大小是按 kB,不是 KB/KiB,但又会显示成 KB。
与 Tab 缩进和解

很长一段时间我都在坚持“2-spaces”缩进,但直到今天我才意识到,这种风格的要点,不在“Space”,因为即使是“Tab”,只要将 size 调整为 2 就行了。

这算是长久以来我对“Tab”的和解,纠结 Spaces or Tabs 是没意义的,现在看来,我只是在纠结缩进的宽度。

在下个项目,我将尝试使用 1-tab 缩进,并设置 tab 的 size 为 2。

这样做有 2 个显而易见的好处:更少的字符占更少的空间;其他人可以根据自身偏好设置 tab 的 size。

BTW:GitHub 也提供了 设置 tab size 的选项,我目前把它设置为 2。

#thinking
在 Go 中复用一个 io.Reader

io.Reader 表示一个 stream,而 stream 只能被读一次。因此有两种复用方式:

一、边读边缓冲到 Buffer

var (
r = strings.NewReader("hello world")
buf = new(bytes.Buffer)
)
foo(io.TeeReader(r, buf))
bar(buf)

二、使用 Pipe,本质是个 ReaderWriter

var (
r = strings.NewReader("hello world")
pr, pw = io.Pipe()
)
go foo(io.TeeReader(r, pw))
go bar(pr)


由于 Pipe 是无 internal buffering 的,因此需要使用两个 goroutine 并行读写。对于多个 Pipe 可以:

var (
r = strings.NewReader("hello world")
pr1, pw1 = io.Pipe()
pr2, pw2 = io.Pipe()
pr3, pw3 = io.Pipe()
)
go foo(pr1)
go bar(pr2)
go baz(pr3)
io.Copy(io.MultiWriter(pw1, pw2, pw3), r)


#experience
Transferable objects in JavaScript

像 Buffer、Stream、Bitmap 这类对象,都做成了 Transferable,它们可以安全地在两个线程间转移,这是一种 zero-copy 操作。

一、在 Worker 之间转移

const u8 = new Uint8Array(1<<10)
const worker = new Worker(URL.createObjectURL(new Blob()))

u8.byteLength // 1024
worker.postMessage(u8, [u8.buffer])
u8.byteLength // 0

二、在 clone 时转移

const u8 = new Uint8Array(1<<10)
u8.byteLength // 1024

const trans = structuredClone(u8, {transfer: [u8.buffer]});
u8.byteLength // 0
trans.byteLength // 1024


#learning