Skip to content

fix(douban): inline normalizeText into splitDoubanTitle for page eval#1854

Open
Benjamin-eecs wants to merge 1 commit into
jackwener:mainfrom
Benjamin-eecs:fix/douban-subject-split-title-scope
Open

fix(douban): inline normalizeText into splitDoubanTitle for page eval#1854
Benjamin-eecs wants to merge 1 commit into
jackwener:mainfrom
Benjamin-eecs:fix/douban-subject-split-title-scope

Conversation

@Benjamin-eecs
Copy link
Copy Markdown
Contributor

@Benjamin-eecs Benjamin-eecs commented Jun 4, 2026

Description

opencli douban subject <id> fails with ReferenceError: normalizeText is not defined thrown at splitDoubanTitle (<anonymous>:5:24), matching the symptom reported in #1851. loadDoubanMovieSubject in clis/douban/utils.js:217 builds its page.evaluate script by inlining splitDoubanTitle.toString() directly into the expression at line 227. Function.prototype.toString() returns only the source of the function body, never its closure, so when the page eval runs in the browser scope it sees a fresh splitDoubanTitle whose body references the module-level helper normalizeText (defined at clis/douban/utils.js:11) that does not exist in that scope. The same eval block already declares a local normalize helper at line 226, but the name does not match what splitDoubanTitle reaches for.

The minimal fix is to make splitDoubanTitle self-contained: inline a normalizeText const at the top of the function so the toString-injected copy carries its own helper. The three existing normalizeText(...) call sites inside the function continue to work, behavior is unchanged, no other caller exists (the function is only invoked in this one page.evaluate, never directly in Node), and the daemon protocol surface is untouched.

Audit of every other *.toString()-injected helper in clis/ confirms none has the same closure-leak shape: resolveDoubanPhotoAssetUrl (clis/douban/utils.js:143) uses only String / URL / regex literals; inferDoubanSearchResultType (clis/douban/utils.js:556) uses only String / Array.isArray / regex literals; looksAuthWallText (clis/reuters/utils.js:94) uses only String / regex; collectCodexProjectsFromDocument (clis/codex/sidebar.js:56) and extractSearchRows (clis/gov-policy/search.js:28) and extractRecentRows (clis/gov-policy/recent.js:28) all define their helpers inside their own function body. splitDoubanTitle was the only outlier; the codebase idiom is that injected helpers must be self-contained, and this PR brings splitDoubanTitle back into that idiom.

Related issue: fixes #1851.

Type of Change

  • 🐛 Bug fix
  • ✨ New feature
  • 🌐 New site adapter
  • 📝 Documentation
  • ♻️ Refactor
  • 🔧 CI / build / tooling

Checklist

  • I ran the checks relevant to this PR
  • I updated tests or docs if needed
  • I included output or screenshots when useful

Screenshots / Output

Pre-fix live repro on upstream main 944ca3a1:

$ node dist/src/main.js douban subject 37116446
ok: false
error:
  code: UNKNOWN
  message: |-
    ReferenceError: normalizeText is not defined
        at splitDoubanTitle (<anonymous>:5:24)
        at <anonymous>:16:3
        at <anonymous>:57:7

Post-fix live verify on this branch with the same subject id from the issue:

$ node dist/src/main.js douban subject 37116446
- id: '37116446'
  type: movie
  title: 给阿嬷的情书
  originalTitle: ''
  year: '2026'
  rating: 9.2
  ratingCount: 783406
  directors: 蓝鸿春
  casts:
    - 李思潼
    - 王彦桐
    - 吴少卿
    - 郑润奇
    - 王晓慧
  country:
    - 中国大陆
  duration: 118
  genres: 剧情,家庭
  url: https://movie.douban.com/subject/37116446/

A new regression test under describe('douban utils') in clis/douban/utils.test.js exercises loadDoubanSubjectDetail(page, '37116446', 'movie') end-to-end by routing the second page.evaluate(...) call through vm.runInNewContext(script, { document, URL }), the same harness runMovieHotEvaluate already uses at clis/douban/utils.test.js:71. The new runMovieSubjectEvaluate(script, elementMap) helper sits next to it at module scope so the two share the same shape and discoverability. Without this PR's fix the test fails with the exact ReferenceError: normalizeText is not defined; with the fix the test asserts title === '海贼王:黄金大冒险' and originalTitle === 'One Piece Gold'. Full douban suite continues to pass: 24/24. cli-manifest.json untouched, no source other than clis/douban/utils.js is touched.

splitDoubanTitle is serialized via toString() into loadDoubanMovieSubject's page.evaluate, so its closure reference to the module-level normalizeText raised ReferenceError in the browser scope and broke douban subject.

Fixes jackwener#1851
@Benjamin-eecs Benjamin-eecs force-pushed the fix/douban-subject-split-title-scope branch from e9403eb to 0b563e1 Compare June 4, 2026 11:29
@Benjamin-eecs Benjamin-eecs marked this pull request as ready for review June 4, 2026 11:32
Copilot AI review requested due to automatic review settings June 4, 2026 11:32
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR addresses a regression where splitDoubanTitle fails when its implementation is stringified and executed inside page.evaluate, and adds a regression test to prevent future breakage.

Changes:

  • Inline normalizeText inside splitDoubanTitle to remove dependency on a module-scope helper during Function.toString() injection.
  • Add a dedicated VM-based evaluation helper for movie subject pages in tests.
  • Add a regression test for loading a movie subject when splitDoubanTitle is toString-injected (issue #1851).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
clis/douban/utils.js Removes closure dependency in splitDoubanTitle by inlining normalization logic.
clis/douban/utils.test.js Adds VM evaluation helper + regression test to ensure movie subject parsing doesn’t throw under toString-injection.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread clis/douban/utils.js
Comment on lines +71 to 75
// Inline normalizeText so the toString-injected copy inside
// loadDoubanMovieSubject's page.evaluate runs without a closure reference
// to the module-level helper (which does not survive Function.toString()).
const normalizeText = (value) => String(value || '').replace(/\s+/g, ' ').trim();
const normalized = normalizeText(fullTitle);
Comment thread clis/douban/utils.test.js
Comment on lines +86 to +88
querySelectorAll() {
return [];
},
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: opencli douban subject <id> command error, unable to query movie details

2 participants